1. 程式人生 > >學JS的心路歷程 -物件與原型(二)

學JS的心路歷程 -物件與原型(二)

昨天有提到說Object.setPrototypeOf可以指定一個物件為另一個物件的原型,但有想過到底這個原型,也就是[[Prototype]]最終會到何處嗎?

答案是Object.prototype!

 

Object.prototype

在第一天有提到說「JS中除了原始型別以外的一切都是物件」。

 

所以每條正常的[[Prototype]]串鏈最頂層的尾端都是內建的Object.setPrototypeOf,這個物件含有JS中各地方所用的常見工具,如toString()、hasOwnProperty()、valueOf()等等,所有正常的物件都應起源於這個Object.setPrototypeOf物件(

vmwork)。

 

建構式與原型

在第八天時,有提到說建構式會經由new呼叫函式,建立一個新的物件:

 

function Foo(){

this.say =“hello”;

}

var a = new Foo();

但其實new Foo()產生一個新的物件a同時,新的物件a的內部會有[[Prototype]]連線至Foo.prototype。

等等,Foo.prototype的.prorotype是什麼鬼東西?函式有自己的原型?

 

「每一個函式都有一個原型物件,會被自動設為透過該函式所建立的物件原型」。

也就是說prototype是當用new建立新的物件時,該新物件的[[Prototype]]。

 

那我們要怎麼看一個物件的原型呢?可以用__proto__或Object.getPrototypeOf()。

 

function Foo(){

this.say =“hello”;

}

var a = new Foo();

 

a.__proto__;//{constructor:ƒ}

Object.getPrototypeOf(a);//{constructor:ƒ}

 

Object.getPrototypeOf(a)=== Foo;//false

Object.getPrototypeOf(a)=== Foo.prototype;//true

用圖表來看可能會比較好理解。

 


好,又有一個奇怪的東西了,什麼是constructor?

函式的原型物件也就是Foo.prototype會具有constructor的屬性,會參照回原來的函式。

我們建立出來的新物件,其原型會被設定為建構式函式原型所參照的物件,可以透過.constructor來存取建立物件的函式以此來作型別檢查。

 

function Foo(){

this.say =“hello”;

}

var a = new Foo();

 

typeof a;//“object”

a instanceof Foo;//true

a.constructor === Foo;//true

a.__proto__.constructor === Foo;//true

所以我們可以用這張圖來表示。

 


使用原型來實現繼承

函式原型是一個物件,所以在繼承實有許多種複製功能的方式。

 

function Person(){};

Person.prototype.say =“Hi”;

 

function trickyMan(){};

trickyMan.prototype = { say:Person.prototype.say};

 

var Jason = new trickyMan();

 

Jason instanceof trickyMan;//true

Jason instanceof Person;//false

執行後發現沒有辦法把Person繼承trickyMan,這只是複製而已。

如果想要真正的原型串鏈,也就是Jason可以是trickyMan,trickyMan可以是Person,一直到最終的Object,應該這樣做:

 

function Person(){};

Person.prototype.say =“Hi”;

 

function trickyMan(){};

trickyMan.prototype = new Person();

 

var Jason = new trickyMan();

 

Jason instanceof trickyMan;//true

Jason instanceof Person;//true

要注意到的是,由於把trickyMan指定為Person的建構物件,所以trickyMan的原本的constructor沒有被任何東西參考,會被棄置且刪除。

我們來看一下圖片(leafor)。

那麼,今天就到這邊,一樣如果有錯誤及來源未附上也歡迎留言指正,那麼我們明天見。