JS constructor探討(一):為什麼要設定prototype.constructor?
阿新 • • 發佈:2019-02-04
每次實現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僅僅可以用於識別物件是由哪個建構函式初始化的,僅此而已。