JS中原型對象中的constructor的作用?

最近被同事問道一個問題:

function Father() {
    this.color = ['red', 'green'];
  }
  function Child() {
    this.test = 1;
  }

  Child.prototype = new Father();

  let instance = new Child();

這個例子是經典原型鏈繼承,未做constructor修復的一個例子。
問:
instance的屬性test哪裏來的,要知道這裏的此時instance的構造函數instance.constructor是Father,我們再根據一般Java,ES6類中的構造函數的拷貝屬性用法,instance的屬性要有也是Father的color?

問題就在這裏了,js的new並不像Java 這種OOP語言的new一樣,js的new後面的不是類,就是普通函數,普通函數以new調用,內部過程爲:MDN,New
test的屬性是通過this的改變獲取到的,壓根沒走js原型對象中的constructor。所以這裏就是一個誤區。

那麼js原型對象中的constructor有什麼作用?上面的繼承讓我們instance.color通過原型鏈訪問到了Father的color屬性,最後爲什麼一般要修復Child.prototype.constructor = Child呢。

答案其實也沒那麼重要:

constructor屬性不影響任何JavaScript的內部屬性。constructor其實沒有什麼用處,只是JavaScript語言設計的歷史遺留物。由於constructor屬性是可以變更的,所以未必真的指向對象的構造函數,只是一個提示。不過,從編程習慣上,我們應該儘量讓對象的constructor指向其構造函數,以維持這個慣例。

目前看到的作用之一,通過實例的構造函數給閉包中的函數增加屬性方法。

var a,b;
(function(){
  function A (arg1,arg2) {
    this.a = 1;
    this.b=2; 
  }

  A.prototype.log = function () {
    console.log(this.a);
  }
  a = new A();
  b = new A();
})()
a.log();
// 1
b.log();
// 1

通過以上代碼我們可以得到兩個對象,a,b,他們同爲類A的實例。因爲A在閉包裏,所以現在我們是不能直接訪問A的,那如果我想給類A增加新方法怎麼辦?

// a.constructor.prototype 在chrome,firefox中可以通過 a.__proto__ 直接訪問
a.constructor.prototype.log2 = function () {
  console.log(this.b)
}

a.log2();
// 2
b.log2();
// 2

通過訪問constructor就可以了。
在這裏插入圖片描述
這位老哥的解釋也就是上面的代碼的一個應用了。

不過你拿到 prototype 也不見得能拿到 正確的 constructor,JS沒有提供方式確保你拿到“正確”的
constructor。我們只能根據慣例相信對象上的 constructor 應該是“正確”的 constructor。

這也是我們上面做constructor修復的一個原因了。

參考:
知乎
紅寶石書

發佈了438 篇原創文章 · 獲贊 72 · 訪問量 37萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章