當咱們在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以後返回的仍是實例化以後的對象。原型

相關文章
相關標籤/搜索