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修復的一個原因了。

參考:
知乎
紅寶石書


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM