iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 23
0
自我挑戰組

學JS的心路歷程系列 第 23

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

  • 分享至 

  • xImage
  •  

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

Object.prototype

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

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

建構式與原型

在第八天時,有提到說建構式會經由 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 可以是 trickyMantrickyMan 可以是 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 沒有被任何東西參考,會被棄置且刪除。
我們來看一下圖片。

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

參考資料:
Javascripter 必須知道的繼承 prototype,[[prototype]],proto
該來理解 JavaScript 的原型鍊了
proto VS. prototype in JavaScript


上一篇
#學JS的心路歷程 Day22-物件與原型(一)
下一篇
學JS的心路歷程 Day24 - 物件與原型(三)
系列文
學JS的心路歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言