首先了解物件導向 (OOP) 有兩種類型,基於類別 (class-based) 以及基於原型 (prototype-based) ,JS 屬於基於原型的語言。
使用 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 出來幫我們解決。
承接上面的問題,在 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
在 JS 中,每個物件都有一個原型,物件可以從原型上繼承方法,這就是為什麼剛剛 const alice = new Person("alice") 之後,明明 alice 沒有 syaHi 這個函式卻還能使用,因為它會從 Person.prototype 去找。
而連接 alice 與 Person.prototype 靠的就是 __proto__。
也就是說 alice.proto 會指向 Person.prototype。
當 Person.prototype 找不到時,就繼續找 Person.prototype.__proto__,直到找不到回傳 null。而透過這個不斷串起來的鏈,就叫做原型鏈。
