前言
先前的筆記中已經談到了用function constructor來建立物件,同時也提到這個概念是模仿其他程式語言來的,然而其他的程式語言會用class
這個關鍵字來設定物件的模板(tamplate),然後用new
來建立物件,這是古典繼承/類別物件導向的程式語言;而 JavaScript始終是一個原型繼承/原型物件導向語言,所以即使看起來很像,本質上是不同的。
因此有許多人認為專注在JS中的原型繼承而不要使用古典繼承會是個好選擇。
而JS中還有一個沒有模仿其他程式語言的建立物件方法,它就是等等我們要談的Object.create()
。
Object.create() 使用
首先,我們先使用這段程式碼建立一個物件的原型
1 | var Person = { |
然後建立一個以Person
為基礎的物件
1 | var john = Object.create(Person); |
輸出的結果如下,它是一個空物件,但是它繼承了 Person
這個物件當中的屬性和方法:
- 透過
Object.create()
可以建立一個空物件,同時可以將帶入Object.create()
的參數內容變成該物件的原型。 Object.create()
是最單純使用原型繼承prototypal inheritance的方式,使用 Object.create() 的方式運用繼承和原型的概念能夠非常簡便的建立物件。
實際應用
如果你想要定一個物件的原型,就先建立一個 A 物件當做其他物件的基礎,然後再建立另一個空物件 B,指稱 A 物件當做它的原型,再透過為 B 物件賦予屬性或方法。
1 | var A = { |
對於 firstName
和 lastName
來說,在 B
物件就已經有這兩個屬性,因此它不會在往該物件的原型__proto
去尋找,而對 getFullName
來說,因為在 B
這個物件裡沒有這個方法,於是就會到 __proto__
裡面去找,最後會回傳"John Doe"
。
關於這個概念考可以參考之前的筆記了解JavaScript中原型(prototype)、原型鍊(prototype chain)和繼承(inheritance)的概念
若瀏覽器不支援
雖然大部分的新瀏覽器都支援這個語法,但如果某些瀏覽器的版本真的舊到無法使用 Object.create()
的話,可以怎麼辦呢?
我們可以利用函數建構子 與「new」的方式新增這個功能。
使用polyfill
polyfill: 有一些舊型瀏覽器引擎不支援某些JavaScript功能,因此有人會自己撰寫一些程式碼來實作相同效果的功能。
1 | // polyfill for Object.create() |
分析程式碼
- 首先先判斷瀏覽器支不支援,如果瀏覽器中查無
Object.create
會回傳布林值false
,再由!
運算子轉換成true
,觸發if
內程式碼。
1 | if (!Object.create) { ... } |
- 由於瀏覽器不支援,所以我們要在JS引擎內建的
Object() 函數建構子
內,自己創造一個名字一樣為create
的方法。
1 | Object.create = function (o) { ... } |
- 如果
Object.create = function (o) { ... }
的傳入參數o
超過一個以上,console回報錯誤訊息。
1 | if (arguments.length > 1) { |
- 建立一個名為
F
的函數建構子。
1 | function F() {}; |
- 在
F
建構子的prototype
當中新增一個物件,該物件是之後使用者回傳入的參數o
1 | F.prototype = o; |
- 回傳一個以
F函數建構子
為基礎,並以new
創造的物件,且該物件的__proto
會繼承F.prototype
內的物件( 也就是使用者傳入的參數o
),如此一來能夠達到Object.create()
的原始效果。
1 | return new F(); |