在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.