首页 > 代码库 > 创建对象
创建对象
1、工厂模式
用函数来封装以特定的接口创建对象的细节
function createPerson (name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o;}var person1 = createPerson("Kang", 88, "teacher");var person2 = createPerson("liu", 33, "DC");
评价:工厂模式虽然解决了创建多个相识对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)
2、构造函数模式
使用该模式创建自定义的构造函数
function Person (name, age, job) { // 使用的是P。按惯例,构造函数始终都应该以一个大写字母开头。 this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); };}var person1 = Person("Kang", 88, "teacher");var person2 = Person("liu", 33, "DC");
这与工厂模式的不同之处:
1)没有显示创建对象
2)直接将属性和方法赋给了this对象
3)没有return语句
优点:
创建自定义的构造函数意味着将来可以将它的实例标志为一种特定的类型,而正是构造函数模式胜过工厂模式的地方:
alert(person1 instanceof Object); // truealert(person1 instanceof Person); // truealert(person2 instanceof Object); // truealert(person2 instanceof Person); // true
缺点:
主要问题是:就是每个方法都要在每个实例上重新创建一遍。
alert(person1.sayName == person2.sayName); // false
3、原型模式
我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。prototype就是通过调用构造函数而创建的那个对象实例的原型对象。
优点:是可以让所有对象实例共享它所包含的属性和方法。换句话来说,不必再构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中:
function Person(){}Person.prototype.name = "Kang";Person.prototype.age = 34;Person.prototype.job = "teacher";Person.prototype.sayName = function(){ alert(this.name);};
与构造函数模式不同的是,新对象的这些属性和方法是有所以实例共享的。
更简单的原型语法:
function Person(){
}
Person.prototype = { name : "Kang", age : 34, job : "teacher", sayName : function(){ alert(this.name); }};
上述中,将Person.prototype设置为等于一个以对象字面量形式创建的新对象,最终结果相同,但有一个例外:constructor属性不再指向Person了。
缺点:
首先,它忽略了为构造函数传递初始化参数这一环节,结构所有实例在默认情况下都将取得相同的属性值。
其次,原型模式的最大问题是由其共享的本性所有导致的。对于包含引用类型值得属性来说,问题就比较突出了。
function Person(){}Person.prototype = { name : "Kang", age : 34, job : "teacher", friends : ["xiaohong", "xiaoming"], sayName : function(){ alert(this.name); }};var person1 = new Person();var person2 = new Person();person1.friends.push("Van");alert(person1.friends); //"xiaohong, xiaoming, Van"alert(person2.friends); //"xiaohong, xiaoming, Van"alert(person1.friends==person2.friends); // true
而这个问题正是我们很少看到有人单独使用原型模式的原因所在。
4、组合使用构造函数模式和原型模式
创建自定义类型的最常见方式,就是组合使用构造函数模式和原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方的引用,最大限度地节省了内存。另外,这种混成模式还支持想构造函数传递参数;可谓是集两种模式之长:
function Person (name, age, job) { this.name = name; this.age = age; thia.job = job; this.friends = ["xiaohong", "xiaoming"];}Person.prototype = { constructor : Person, sayName : function () { alert(this.name); }}var person1 = createPerson("Kang", 88, "teacher");var person2 = createPerson("liu", 33, "DC");person1.friends.push("Van");alert(person1.friends); //"xiaohong, xiaoming, Van"alert(person2.friends); //"xiaohong, xiaoming"alert(person1.friends==person2.friends); // false
在这个例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性constructor和方法sayName()则是在原型中定义的。而修改了person1.friends并不会影响person2.friends,因为它们分别引用了不同的数组。
这种混合模式是目前使用最广泛的,认同度最高的一种创建自定义类型的方法。
创建对象