JavaScript 沒有像其他物件導向程式設計的語言一樣,有內建 class 的機制,就算是 ES6 的 class 也只是語法糖,不過我們還是可以設計出一個類似 class 機制的功能,而可以達成這個目標靠的就是 原型鏈(Prototype Chain)。
new
在 Java,我們要在一個 class 建一個新的 Instance 時,可以這樣寫:
Person p1 = new Person();
這行程式碼會建立一個 Person
的 instance 叫做 p1
,而 JavaScript 也有 new
這個關鍵字,而 JavaScript 並沒有 class,所以後面接的會是一個 constructor function(建構函式),就像是 Java 在 new
一個新的 instance 時,都會呼叫 class 的 constructor(建構子)。
舉例來說,有個叫做 Person
的建構函式,p1
是一個 Person
的 instance。
function Person(name) {
this.name = name
}
var p1 = new Person('allen')
console.log(p1) // Person, { name: 'allen' }
這時建構函式裡面的 this
就是這個新的 instance p1
。
我們也可以在 Person
裡面加入一些方法,並再建立一個新的 instance,也會同時有 name
跟 sayHello
可以用。
function Person(name) {
this.name = name
this.sayHello = function() {
console.log(this.name + ': hello~')
}
}
var p1 = new Person('allen')
var p2 = new Person('kaneshiro')
p1.sayHello() // allen: hello~
p2.sayHello() // kaneshiro: hello~
new 的小問題
我們現在的設計,沒有辦法共享這些屬性跟方法,這是什麼意思?p1
跟 p2
不是都有 name
跟 sayHello
嗎?
我們可以做一個測試就知道為什麼會這樣說了。
function Person(name) {
this.name = name
this.sayHello = function() {
console.log(this.name + ': hello~')
}
}
var p1 = new Person('allen')
var p2 = new Person('kaneshiro')
console.log(p1.sayHello === p2.sayHello) // false
也就是說,p1
跟 p2
的 sayHello
是兩個不一樣的 function,頂多只是做一樣的事情而已,他們會各自占用一部分記憶體,如果有一百個甚至更多個 instance,他們各自的屬性跟方法就會各自占用一部份的空間,即使他們完全相同,造成很大的浪費。
Prototype
這時就用到了一個叫做 prototype
的屬性,只要把我們想要共享的屬性或方法,放到 prototype
,所有 Person
的 instance 就可以共用這些屬性和方法,而其他不需要共享的就放在建構函式裡。
function Person(name) {
this.name = name
}
Person.prototype.sayHello = function() {
console.log(this.name + ': hello~')
}
var p1 = new Person('allen')
var p2 = new Person('kaneshiro')
p1.sayHello() // allen: hello~
p2.sayHello() // kaneshiro: hello~
console.log(p1.sayHello === p2.sayHello) // true
我們可以看到 p1
跟 p2
用的的確是同一個 sayHello
,而且功能完全一樣。
總結
我們宣告了一個叫做 Person
的函式,這個函式可以稱為建構函式(constructor function),並把它當作 constructor 使用,我們還可以在 Person.prototype
加上你想要讓 instances 共享的屬性和方法。
再來用 var p1 = new Person('allen')
來建立一個新的 instance,而 p1
就可以有自己的 name
,還有跟其他 instances 共用的 sayHello
,這樣看起來就很像是 p1
繼承了 Person
的 prototype
。