1. 程式人生 > >JS constructor探討(一):為什麼要設定prototype.constructor?

JS constructor探討(一):為什麼要設定prototype.constructor?

每次實現JS的繼承時,程式碼裡必有如下兩句:

//  用於設定原型
Employee.prototype = new Person()
//  設定原型的構造器
Employee.prototype.constructor=Employee

實現原型鏈就靠第一句話,但第二句話有什麼用呢?

先看示例程式碼:

function Person(username) {
    this.username = username;
}
Person.prototype.setUsername = function(name) {
    this.username = name;
}
//  繼承Person
function Employee(username, company) { Person.call(this, username); this.company = company; } // 設定原型 Employee.prototype = new Person() Employee.prototype.constructor=Employee // 測試程式碼 var yiifaa = new Employee('yiifaa', '360')

1. 會影響原型鏈嗎?

其實可以很容易反證,如果影響原型鏈的話,constructor應該設定為Person才對,否則不就形成死迴圈了嗎?

//  顯然,prototype與constructor已經形成了雙向聯絡
//  結果恆為真
Employee.prototype.constructor.prototype.constructor === Employee

建立原型鏈主要靠proto屬性,如下:

//  顯然,通過__proto__可以連結到原型的頂端
//  結果恆為真
Employee.prototype.__proto__ === Person.prototype
Person.prototype.__proto__ == Object.prototype

於是

//  一直獲取到原型鏈的頂端
Employee.prototype.__proto__.__proto__  === Object
.prototype

由上面的程式碼可以看出,constructor對原型鏈毫無影響。

2. 會影響instanceof嗎?

經過測試,無論有沒有設定prototype.constructor,以下恆為真

yiifaa instanceof Employee
yiifaa instanceof Person

所以對instanceof毫無影響,那好問題來了,如何改變instanceof的結果呢?方法如下:

Person.prototype = {}
//  現在為false
yiifaa instanceof Person

為什麼呢?因為現在原型鏈的鏈已經斷了,證明如下:

Employee.prototype.__proto__ !== Person.prototype

那怎麼改回來呢?

Person.prototype = Employee.prototype.__proto__
//  現在測試恆為真
yiifaa instanceof Person

3. 會影響ownProperty嗎?

顯然,ownProperty只取決於建構函式,而不是建構函式的屬性。

5. 最佳應用場景

於是constructor的最佳應用場景為型別判斷,如下:

var arr = []
//  恆為真
arr.constructor === Array
var num = 2
//  恆為真
num.constructor === Number
var str = '123'
//  恆為真
str.constructor === String

6. 結論

prototype.constructor僅僅可以用於識別物件是由哪個建構函式初始化的,僅此而已。