当咱们在JavaScript中new一个对象的时候,咱们到底在作什么

JavaScript里实例化一个对象的时候,咱们经常使用的方法就是使用new操做符。浏览器

var Foo = function(x, y) {
    this.x = x
    this.y = y
}

var foo = new Foo(1, 2) // Foo {x: 1, y: 2}

那么new操做符到底作了哪些工做?咱们能够看一下foo这个对象究竟是一个怎样的对象。函数

首先,foo自己是一个对象,而后,他自己有两个属性,xy。同时,在大多数浏览器的控制台上,咱们还能看到一个颜色稍浅的属性,叫__proto__,他有两个属性,constructor__proto__this

__proto__是一个访问器属性。他指向的是当前对象自己的[[Prototype]],这个[[Prototype]]并非一个属性,他只是一个符号,表明的是构造函数Foo的原型对象Foo.prototype的,具体能够参考一下MDN上的描述prototype

foo.__proto__ === Foo.prototype // true

因此,咱们大体描述一下code

var Foo = function(x, y) {
    this.x = x
    this.y = y
}

// 1. 建立一个空对象
var foo = {}

// 2. 调用构造函数,而且将构造函数的`this`指向foo
Foo.call(foo, 1, 2)

// 3. foo继承Foo的原型对象
foo.__proto__ = Foo.prototype

等等,虽然咱们上面这么写最后foo的确跟new Foo()出来的对象是同样的,可是状况并不单单这么简单。对象

咱们知道,new操做符操做的是一个函数,在上面的栗子里,函数Foo并无显式地返回任何值,因此执行这个函数以后,返回值是undefined。当构造函数没有显式地返回一个值的时候,对其执行new操做以后,会返回这个构造函数实例化以后的对象。继承

那若是我返回了某个值呢?ip

var Foo = function(x, y) {
    this.x = x
    this.y = y

    return {
        a: this.x
    }
}

var foo = new Foo(1, 2) // {a: 1}

foo就是执行这个函数以后的返回值,那么这个时候new Foo()Foo()就没有任何区别了,因此一般状况下,咱们并不会选择在一个构造函数里返回某个值。get

特别要注意的是,若是你在构造函数里返回的不是一个对象,而是一个普通的值,好比说一个Number类型或者String类型的值,那么new以后返回的仍是实例化以后的对象。原型

相关文章
相关标签/搜索