我們在上篇說到了工廠模式和構造函數模式,結尾說到解決構造函數模式的缺點的方法是引入了原型模式,本篇就來說說原型模式及其與構造函數模式的組合使用。
一、原型模式
function Person() {
}
Person.prototype.name = 'Jack';
Person.prototype.friends = ['Lily', 'John'];
var person1 = new Person();
var person2 = new Person();
console.log(person1.name);//Jack
console.log(person2.name);//Jack
由於person1和person2都是Person的實例,所以都能訪問他們共同的原型對象上的name屬性。
然而,原型模式也有缺點,繼續上邊的代碼執行以下代碼:
person1.friends.push('Lucy');
console.log(person1.friends);//["Lily", "John", "Lucy"]
console.log(person2.friends);//["Lily", "John", "Lucy"]
由於friends屬性定義在原型對象上,所以一旦改變,所有實例都會改變,顯然實際中這不是我們期望的,我們希望各自的friends屬性互不影響;爲解決這一問題,我們採用了原型模式和構造函數的組合使用;
二、組合使用原型模式和構造函數模式
繼續上邊的例子,我們將實例需要獨自擁有的屬性或方法定義在構造函數裏邊,將共享的屬性或者方法定義在原型對象中,舉例如下:
function Person(name) {
this.name=name;
this.friends=['Jack'];
}
Person.prototype.sayName=function(){
console.log(this.name);
};
var person1 = new Person('Alice');
var person2 = new Person('Bob');
person1.sayName();//Alice
person2.sayName();//Bob
person1.friends.push('Lucy');
console.log(person1.friends);//["Jack", "Lucy"]
console.log(person2.friends);//["Jack"]
可以看到,構造函數裏邊的name和friends屬性各實例分別擁有自己的一份,不會互相干擾,sayName方法所有實例共享。