0%

淺談 Prototype 原型鍊與建構式概念

文章目的

撰寫建構式原型的好處是我們將可以重複使用的方法寫在原型內,以減少記憶體的負擔,藉此篇文章紀錄 JavaScript 原型鍊與建構式介紹增加自己的開發邏輯思維。

何謂原型

我們在使用一些物件或是陣列方法時,有時候很多屬性我們都能使用但卻沒看到它存在陣列或物件內,原因就是這些屬性都存在原型內,像是陣列的 filterforEach 等。
原型會預設存在一些屬性方法供我們在操作時調用。
原型有個特點是它會向上尋找,也就是說系統在我們定義的方法中找不到相關方法時會向上尋找原型內是否有符合的方法。
陣列原型向上就是物件原型。
在 console 中我們看到的原型就會如下圖所示

類陣列

有時候我們在觀察時會發現明明長得很像陣列,但原型卻不是顯示 Array,這就是所謂的類陣列,類陣列無法使用陣列的方法,當我們需要使用時,可以利用 ES6 的展開將它轉換成陣列,方法如下:

1
[...類陣列]

原型共用概念

這邊有一個重要的概念是所有原型是共有的,也就是說每一個物件或陣列它的原型都相同。
例如我們自訂一個物件或陣列原型的屬性,這個屬性就會存在所有的物件或陣列原型內,至於如何自訂,可以參考以下方法:

1
2
某一個物件或陣列.__proto__.test = '測試' // 所有的物件原型都會有這屬性,但不建議這樣寫,可以改用下面的寫法
某一個物件或陣列.prototype.test = '測試' // 此方法僅限使用在建構式

何謂建構式

我們在複製物件時,會遇到一個問題也就是傳參考,因為物件的這個特性,當我們修改複製過來物件內的屬性值時,原物件也會被修改到,為了避免這情形,建構式就是一個方法。
建構式的概念是我們建立一個模板,接著我們透過 new 的方式將特定參數傳入模板中,使這個模板變成客製化的物件,這邊看一下範例程式碼會比較好理解:

1
2
3
4
5
6
7
function PhoneTemplate (brand, withCamera) {  // 模板,一般來講建構式第一個字母會是大寫
this.brand = brand;
this.withCamera = withCamera;
}

var iPhone = new PhoneTemplate('Apple', true)
console.log(iPhone) // PhoneTemplate {brand: "Apple", withCamera: true}

將原型與建構式搭配

當我們要在建構式自訂義方法時,就可以使用到原型,原因是因為原型繼承的概念,以下是範例程式碼:

1
2
3
4
5
PhoneTemplate.prototype.callSomeone = function (someone) { //儲存在物件原型內的方法
console.log(this.brand + ' 打通電話給 ' + someone)
}
var iPhone = new PhoneTemplate('Apple', true)
iPhone.callSomeone('小明') // Apple 打通電話給小明

這邊有一點要注意,使用 prototype 來自訂原型時一定是建立在我們的模板上,以此範例來說就是 PhoneTemplate。
補充:當我們想要利用 console.log 觀察原型時,觀察不到的情況下可以改寫成 console.dir。

參考資料

JavaScript 建構式與原型
JavaScript 原型鍊與建構式