创建自定义类型最常见的就是组合使用构造函数模式和原型模式。构造函数模式用于定义实例的属性。而原型模式我们上节了解到,主要是用于定义公用的属性和方法。
首先看一下构造函数模式创建js对象.
1. 构造函数模式
构造函数模式可以用来创建特定类型的对象
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName= function(){
alert(this.name)
};
}
var person1 = new Person("zhangsan", 29, "Software Enginner");
var person1 = new Person("lisi", 31, "Doctor");
即要创建Person新实例,必须使用new操作符。person1和person2分别保存着Person的一个不同的实例,这两个对象都有constructor属性,且都指向Person。
alert(person1.constructor == Person); //true;
alert(person2.constructor == Person); //true;
两个实例相当于都有了构造函数的一个副本,在一个实例中修改属性或者方法,不会影响到另一个实例中的属性和方法。
如:
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName= function(){
return (this.name)
};
}
var person1 = new Person("zhangsan", 29, "Software Enginner");
var person2 = new Person("lisi", 31, "Doctor");
person1.name = "wangwu";
alert(person1.sayName());//wangwu
alert(person2.sayName());//lisi
}
所以说构造函数主要用来定义实例特有的属性和方法。而原型模式上节讲过用来定义共享的属性和方法。如果将两者结合起来,就会使实例具有自己特有的属性和方法,又有共享的属性和方法。于是就出现了,
2. 组合使用构造函数和原型模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ['aa', 'bb'];
}
Person.prototype = {
constructor:Person,
SayName : function(){
alert(this.name);
}
}
var person1 = new Person("zhangsan", 29, "Software Enginner");
var person2 = new Person("lisi", 31, "Doctor");
person1.friends.push('cc');
alert(person1.friends); //aa, bb, cc
alert(person2.friends); // aa, bb
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
实例中的属性都是在构造函数中定义的。由实例所共享的属性constructor和方法则是在原型对象中定义的。修改了person1中的friends方法并不会影响person2中的方法。这也是构造函数的特性。
这种构造函数与原型模式混成的模式,目前在ECMAScript中使用最广泛,认同度最高的一种创建自定义类型的方法,可以说这是用来定义引用类型的一种默认模式。
3. 动态原型模式
在上面介绍了构造函数模式与组合使用构造函数模式和原型模式之后,又引入了动态原型模式。
动态原型模式将所有信息都封装在了构造函数中,而通过在构造函数中初始化原型(如果有必要的话),又保持了同时使用构造函数与原型的优点。
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
alert (this.name);
}
}
这样只有在sayName方法不存在的情况下,才会将它添加到原型中。这里对原型所做的修改,会立即在实例中反映出来。
注意:使用动态原型模式时,不能使用对象字面量来重写原型。这样会切断所有实例与新原型之间的联系。