在JavaScript中虽然说能够用Object的构造函数或者字面量建立单个对象,可是用这些方式来建立多个对象时就有一个明显的缺点,产生了大量的重复代码。为解决这些问题,许多模式就应运而生。c#
1. 工厂模式函数
因为在ECMAScript中没法建立类,因此就发明了一种函数,用来封装以特定接口建立对象的细节。this
可是以这种方式建立的对象没有解决对象识别问题,即怎样知道一个对象的类型。spa
function createPerson(name,age,job) { var o = new Object(); o.name=name; o.age=age; o.job=job; o.sayHellow=function() {alert("Hellow"+o.name)}; return o; } var person1 = createPerson("Jack",34,"Doctor");
2. 构造函数模式prototype
这种方式建立的对象都是属于同一类型的,下面的例子中,全部的对象都是Person类型。指针
function Person(name,age,job) { this.name=name; this.age=age; this.job=job; this.sayName = function() { alert("Hello, "+this.name); } } var person1 = new Person("Jack",24,"Doctor"); var person2 = new Person("Simon",34,"Teacher"); alert(person1 instanceof Object); // true alert(person1 instanceof Person); // true alert(person2 instanceof Object); // true alert(person2 instanceof Person); // true
可是这个模式也有缺点,那就是每一个方法都要在每一个对象的实例中从新建立一遍。就如上面的例子,person1 和person2的sayName方法其实不是Function的同一个实例,是位于两个不一样位置的函数指针。code
因此能够改进下:对象
function Person(name,age,job) { this.name=name; this.age=age; this.job=job; this.sayName = sayName; } function sayName() { alert("Hello, "+this.name); } var person1 = new Person("Jack",24,"Doctor"); var person2 = new Person("Simon",34,"Teacher"); alert(person1 instanceof Object); // true alert(person1 instanceof Person); // true alert(person2 instanceof Object); // true alert(person2 instanceof Person); // true
3. 原型模式blog
想弄明白这个模式,必需要想理解prototype.接口
这个模式有个很大的问题,就是全部对象的属性和方法都是共享的,可是咱们可能仅仅想让Person类共享这个sayName 方法,你们应该都想到了,能够用构造函数模式+原型模式来解决这个问题。
function Person(){} Person.prototype.name="Jack"; Person.prototype.age=33; Person.prototype.job="IT"; Person.prototype.sayName = function(){alert("Hellow"+ this.name);}; // 字面量写法 function Person(){} Person.prototype = { name: "Jack", age: 33, job: "IT", sayName=function(){alert("Hellow "+this.name);} }
4. 组合使用构造函数模式和原型模式
用构造函数定义实例属性,存放不共享的数据,用原型模式定义共享的方法和属性,这样能够尽最大可能减小内存开销。
有点相似于c#类的实例成员和静态成员,但只是像。
这中模式是目前用的最普遍,承认太最高的。
function Person(name,age,job) { this.name=name; this.age=age; this.job=job; this.friends=["Toby","Linford"]; } Person.prototype= { constructor: Person, sayName: function(){alert(this.name);} } var person1 = new Person("Jack",33,"SDE"); var person2 = new Person("Lucy",25,"Teacher"); person1.friends.push("Jim"); alert(person1.friends); // Toby,Linford,Jim alert(person2.friends); // Toby,Linford alert(person1.friends==person2.friends); // false alert(person1.sayName==person2.sayName); //true
5.动态原型模式
function Person(name,age,job) { this.name=name; this.age=age; this.job=job; if(typeof sayName != "function") { Person.prototype.sayName=function() { alert(this.name); } }; }
6. 寄生构造函数模式
其基本思想就是一个函数,该函数的做用仅仅就是封装建立对象的代码,而后再返回新建立的对象。
function createPerson(name,age,job) { var o = new Object(); o.name=name; o.age=age; o.job=job; o.sayHellow=function() {alert("Hellow"+o.name)}; return o; } var person1 = createPerson("Jack",34,"Doctor");
从上面代码看来和工厂模式是同样的。可是这个模式能够在特殊的状况为对象(特别是内置的对象,如Array)添加构造函数。
7.稳妥构造函数模式
和寄生构造函数模式相似,但有两个不一样点,一是建立对象的实例方法不引用this,二是不使用new 调用构造函数。
function Person(name, age, job) { //定义要返回的对象 var o = new Object(); //定义私有变量和方法 //添加方法 o.sayName=function(){alert(name);}; return o; }
在上面的例子中,只有经过sayName才能够访问name.