1.工厂模式
解决了创建多个相似对象的问题。但却没有解决对象识别的问题(即怎样知道一个对象的类型)。
考虑到ECMAScript中无法创建类,开发人员发明了一种函数,用函数来封装以特定接口创建对象的细节。
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("Nicholas",29,"Software Engineer"); var person2 = createPerson("Greg",27,"Doctor");
2.构造函数模式
创建自定义的函数意味着将来可以将它的实例标识为一种特定的类型。但是每个方法都要在每个实例上重新创建一遍。ECMAScript中函数是对象,因此每定义一个函数,就是实例化了一个对象。
function Person(name,age,job){ this.name=name; this.age=age; this.job=job; this.sayName=function(){ alert(this.name); }; } var person1 = new Person("Nicholas",29,"Software Engineer"); var person2 = new Person("Greg",27,"Doctor");
3.原型模式
不必再构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。
function Person(){ } Person.prototype.name="Nicholas"; Person.prototype.age=29; Person.prototype.job="Software Engineer"; Person.prototype.sayName=function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); person1.name="Greg"; alert(person1.name);//Greg——来自实例 alert(person2.name);//Nicholas——来自原型
更简单的原型语法(对象字面量)
function Person(){ } Person.prototype={
constructor:Person,//设置回适当的值 name:"Nicholas", age:29, job:"Software Engineer", sayName:function(){ alert(this,name); } };
(我们将Person.prototype设置为等于一个以对象字面量形式创建的新对象。最终结果相同,但有一个例外,constructor属性不再指向Person了。这里的语法完全重写了默认的prototype对象。)
但是1.它省略了为构造函数传递初始化参数这一环节,结果所有的实例在默认情况下都将取得相同的属性值。2.原型中的实例是被很多实例共享的,这种共享对于函数非常合适,对于那些包含基本类型值的属性也说得过去,毕竟,通过在实例上添加一个同名属性,可以隐藏原型中的对应属性。然而,对于包含引用类型值的属性来说,问题就比较突出了。
function Person(){ } Person.prototype={ constructor:Person, name:"Nicholas", age:29, job:"Software Engineer", friends:["Shelby","Court"], sayName:function(){ alert(this,name); } }; var person1 = new Person(); var person2 = new Person(); person1.friends.push("Van"); alert(person1.friends);//Shelby,Court,Van alert(person2.friends);//Shelby,Court,Van alert(person1.friends==person2.friends);//true
4.组合使用构造函数模式和原型模式
构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。
function Person(name,age,job){ this.name=name; this.age=age; this.job=job; this.friends=["Shelby","Court"]; } Person.prototype={ constructor:Person, sayName:function(){ alert(this.name); } } var person1 = new Person("Nicholas",29,"Software Engineer"); var person2 = new Person("Greg",27,"Doctor"); person1.friends.push("Van"); alert(person1.friends); alert(person2.friends); alert(person1.friends==person2.friends); alert(person1.sayName==person2.sayName);