什麼是原型模式?
原型模式屬於創建型模式。是基於現有對象模版,通過克隆的方式創建新的對象。
解決什麼問題?
比如定義一個 person1 的對象
const person1 = {
name: 'zkk',
age: 18,
sex: 'male',
hobby: 'daydream',
sayName: function() {
console.log(this.name)
}
}
再定義一個 person2 對象
const person2 = {
name: 'yy',
age: 18,
sex: 'female',
hobby: 'wander',
sayName: function() {
console.log(this.name)
}
}
我們發現 person1 和 person2 定義了相同的屬性,如此定義對象,生成了大量的重複代碼,也沒有達到代碼複用的目的。
如何解決上面的問題呢?
高程在第六章 6.2 創建對象一節,作者提出了很多解決方法,比如工廠模式,構造函數模式。其中就有原型模式。通過原型模式實現繼承是解決的此類問題的關鍵。與此同時,所有子對象的函數,都指向模版對象(原型)中定義的同一個函數,而不是創建自己的單獨拷貝,因此帶來了性能的提升。
實現
如果是基於類構建對象的其他語言(如 Java),爲了實現原型模式,可能還需要繼承接口等一系列操作。但是 JS 本身就是基於原型設計的語言,我們可以通過 Object.create 來實現原型模式。
// 定義原型
const person = {
name: '',
age: 0,
sex: '',
hobby: '',
sayName: function() {
console.log(this.name)
}
}
// 通過原型克隆新對象
const person1 = Object.create(person)
person1.name = 'zkk'
person1.sayName() // => 'zkk'
// Object.create 還可以提供第二個參數,來初始化對象屬性。
const person1 = Object.create(person, {
name: {
value: 'zkk'
}
})
我們也可以模擬 Object.create 的實現
function createObj(obj) {
function F(){}
F.prototype = obj
return new F()
}
這裏使用到了構造函數,但沒有初始化的部分,僅僅是希望將對象鏈接至原型。
在實際的使用場景中,我們也會組合構造器模式和原型模式,一起來創建對象。