iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0
自我挑戰組

菜鳥前端修練之旅系列 第 14

Day 14 | JS 中的原型鍊

  • 分享至 

  • xImage
  •  

首先了解物件導向(OOP)有兩種類型,有基於類別(class-based)以及基於原型(prototype-based)兩種,JavaScript 屬於後者 - 基於原型的語言。

建構式(Constructor)

使用 new 建立新的物件時,所執行的函式稱為建構式,用來初始化物件以及建立初始化屬性。

const Person = function(name){
    this.name = name;
    this.sayHi = function(){
        console.log("Hi")
    }
}

// new 一個 instance 
const peter = new Person("Peter")

了解建構式之後我們來看上面的程式碼有哪些問題:

這邊的 Person 有個 sayHi 的函式,於是我再 new 一個人出來。

const alice = new Person("Alice")

然後比較兩個人的 sayHi() 後發現:

console.log(peter.sayHi === alice.sayHi) // false

回傳 false 代表這兩個 function 明明都是同個方法,但各占了不同的記憶體,所以這樣明顯不好。

那要怎麼辦? 我們請 prototype 出來幫我們解決。

原型(Prototype)

承接上面的問題,我們改在 Person.prototype 中新增方法。

const Person = function(name){
    this.name = name;
}

Person.prototype.sayHi = function(){
    console.log("Hi")
}

同樣的,new 出來的 instance 都有 sayHi 這個方法,這時候我們再比較一次:

console.log(peter.sayHi === alice.sayHi) // true

在 JavaScript 中,每個物件都有一個原型,物件可以從原型上繼承方法。

這就是為什麼剛剛 const alice = new Person("alice") 之後,明明 alice 沒有 syaHi 這個函式卻還能使用,因為它會從 Person.prototype 去找。

而連接 alice 與 Person.prototype 靠的就是 proto

也就是說 alice.proto 會指向 Person.prototype。

當 Person.prototype 找不到時,就繼續找 Person.prototype.proto,直到找不到回傳 null。而透過這個不斷串起來的鏈,就叫做原型鏈。


這也是為什麼我們的 array 可以直接使用 filter、forEach 等方法,我們將陣列的 proto 印出來看看:

const arr = [];

console.log(arr.__proto__)

console.log(arr.__proto__.__proto__) //null

class

ES6 中新增了 class 供我們使用,也可以使用繼承。不過 class 只是語法糖,這點不要搞混了。

以下實際建立一個 class:

class Animal {
    constructor(name) {
        this.name = name;
    }

    eat(){
        console.log("我愛吃飼料");
    }
}

const dog = new Animal("dog");

上面的 eat() 會放到 Animal.prototype

不過如果有使用 privateprotectedabstract 等需求的話,只能使用 TypeScript 來撰寫。

參考資料


上一篇
Day 13 | 提升(Hosting)
下一篇
Day 15 | call(), apply(), bind()
系列文
菜鳥前端修練之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言