回顧Javascript構造函數

長期更新文章 喜歡的start下 github.com/aototo/blogjavascript

構造函數已是老生常談的事情了。這裏講一些比較基礎的東西。java

先看下一個例子git

function Book(name) { 
    if (!(this instanceof Book)) { 
        // the constructor was called without "new".
        return new Book(name);
    } 
}

var myBook = Book(name);
var myBook1 = Book(name);
myBook.constructor === myBook1.constructor // true複製代碼

首先判斷this是否爲Book的實例,不是就返回新的實例。常常用於解決在構造函數前面忘記使用new的狀況,若是沒有使用在function前面使用new,那就按正常的函數執行。那爲何這裏能夠這麼使用?github

咱們先看下new的原理bash

(1) 建立一個新的對象: var myBook = New Object()
(2) 設置對象的__proto__ 指向構造函數的prototype
    myBook.__proto__ = Book.prototype複製代碼

到了第二步驟咱們就能夠看到myBook能夠訪問構造函數的prototype的constructor。函數

var myBook = New Object();
myBook.__proto__ = Book.prototype;
myBook instanceof Book // true複製代碼

當執行第二步驟之後例子中的 if (!(this instanceof Book)) 就不會被執行。因此this instanceof Book能夠判斷當前函數是否使用new。從而避免開發者忽略而形成程序錯誤的狀況。ui

(3)第三步就是執行Book函數,而且讓this指向myBook對象複製代碼

第四步就是判斷Book返回值的類型:this

判斷條件
(1)若是是值類型就丟棄,返回instance。
(2)若是是引用類型,就返回這個引用類型的對象,替換掉instance。複製代碼

例子:spa

function Book() {
    return 2;
}
var myBook = new Book();
myBook instanceof Book // true複製代碼

return 2屬於值類型,包括String、布爾值、null、undefined等..若是是值類型,就丟棄返回instance。prototype

function Book() {
    var newObj = {}
    return newObj;
}
var myBook = new Book();
myBook instanceof Book // false複製代碼

若是是引用類型,就返回這個引用類型的對象

function Book() {
    return new Number();
}
...複製代碼

若是return的值是一個Number 對象,那麼實例對象的值就是Number 對象。

使用Object.create()建立的對象其proto 並非指向構造函數。

原型鏈繼承須要注意的一點

例子:

function Car() {}
function Bmw() {}

Bmw.prototype = new Car();
Bmw.prototype.constructor = Bmw; 

var bmw1 = new Bmw();複製代碼

比較奇怪的是 Bmw.prototype.constructor = Bmw; 解釋下爲何要這麼處理。
假設若是沒有這行

bmw1.constructor === Car //true複製代碼

Bmw.prototype 其實是 new Car() 的實例,結果致使Bmw prototype中的 constructor從丟失(ps: function建立後prototype已經有constructor值),
bmw1對象在原型鏈中查詢constructor的時候指向了構造函數Car,這明顯是錯誤的。所以這裏修正了Bmw.prototype.constructor = Bmw。同時還能夠經過proto獲取Car的構造函數。

bmw1.__proto__.__proto__.constructor === Car複製代碼
相關文章
相關標籤/搜索