原型对象
问题
最大的问题:共享的本性导致的。
一个属性如果包含引用类型值,原型对象上的改属性修改的话,会导致所有实例的改属性变化。
function Person(){
}
Person.prototype = {
constructor: Person,
name: 'wang',
age: 18,
friends: ['Tom', 'Jack'], // 引用数据类型
sayName: function(){
alert(this.name);
}
}
var person1 = new Person();
var person2 = new Person();
person1.friends.push('May');
console.log(person1.friends); // [ 'Tom', 'Jack', 'May' ]
console.log(person2.friends); // [ 'Tom', 'Jack', 'May' ]
console.log(person1.friends === person2.friends)// true
组合使用构造函数模式和原型模式 (最常用的模式)
最常见的组合 构造函数模式+原型模式
构造函数模式:用于定义实例属性
原型模式:用于定义方法和共享属性
function Person(name, age){
this.name = name;
this.age = age;
this.friends = ['Tom', 'Jack'];
}
Person.prototype = {
constructor: Person,
sayName: function(){
alert(this.name);
}
}
var person1 = new Person();
var person2 = new Person();
person1.friends.push('May');
console.log(person1.friends); // [ 'Tom', 'Jack', 'May' ]
console.log(person2.friends); // [ 'Tom', 'Jack' ]
console.log(person1.friends === person2.friends); // false
动态原型模式
特点:把所有信息都封装进构造函数,通过在构造函数中,初始化原型(仅在必要情况下),又同时使用了构造函数和原型的优点。换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。
缺点:不能使用对象字面量重写原型,如果在已经构建实例的情况下重写,会切断现有实例和新原型之间的联系。
function Person(name, age){
// 属性
this.name = name;
this.age = age;
this.friends = ['Tom', 'Jack'];
// 方法
if(typeof this.sayName != 'function'){
Person.prototype.sayName = function(){
alert(this.name);
}
}
}
寄生构造函数模式
基本思想:创建一个函数,该函数作用仅仅是封装创建对象的代码,然后再返回新的对象;很像典型的构造函数。(其实和工厂函数一模一样)。
例子:
function Person(name, age){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function () {
console.log(this.name);
}
return o;
}
var person1 = new Person('wang', 18);
person1.sayName()
假如我们想给数组加一个特殊的方法,不能直接去改Array的构造函数,可以用这个模式实现:
function SpecialArray(...args) {
// 创建数组
var values = new Array();
// 添加值
values.push.apply(values, args);
// 添加方法
values.toPipedString = function () {
return this.join('+')
}
// 返回数组
return values;
}
var animals = new SpecialArray('dog','pig','cat');
console.log(animals.toPipedString());
寄生构造函数模式,返回的对象与构造函数或者构造函数的原型属性之间没有关系。不能依赖instanceof
操作符确定对象类型。不要使用这种模式。
稳妥构造函数模式
稳妥对象:没有公共属性,而且其方法也不引用this的对象。
与寄生模式类似,instanceof
操作符对这种对象也没有意义。
function Person(name, age){
var o = new Object();
o.sayName = function () {
console.log(name);
}
return o;
}
var person1 = Person('wang', 18);
person1.sayName()
非常安全,除了sayName()
方法外,没有别的方式可以访问其数据成员。