一、工廠模式
function createPerson(name, age) { var o = new Object(); o.name = name; o.age = age; o.say = function () { alert(this.name); }; return o;
}
每次調用這個函數都會返回一個包含兩個屬性和一個方法的對象。
二、構造函數模式
js中的構造函數可以用來創建特定類型的對象,像object和array這樣的原生構造函數,在運行時會自動出現在執行環境中。此外,也是可以創建自定義的構造函數,從而定義自定義對象類型的屬性和方法。
1 function Person(name,age){ 2 this.name = name; 3 this.age = age; 4 this.say = function(){ 5 alert(this.name); 6 } 7 } 8 var person1 = new Person("xiaoming","18");
構造函數也是函數,只是調用他們的方式不同,任何函數,只要通過new操作符調用,則它就可以作為構造函數;不通過new操作符調用,則就是普通函數。
1、當做構造函數
1 var person1 = new Person("xiaoming",18); 2 person1.say(); // xiaoming
2、當做普通函數
1 Person("xiaozhu",20); //添加到window 2 window.say(); // xiaozhu
三、原型模式
我們創建的每一個函數都有一個prototype(原型)屬性,這個屬性是一個指針,指向一個對象,這個對象包含所有實例共享的屬性和方法。按照字面意思,那么prototype就是通過調用構造函數而創建的對象實例的原型對象。使用它的好處是,可以讓所有對象實例共享原型中所包含的屬性和方法。
1 function Person(){} 2 Person.prototype.name="xiaoming"; 3 Person.prototype.age=18; 4 Person.prototype.say=function(){ 5 alert(this.name); 6 } 7 var person1=new Person(); 8 person1.say(); // xiaoming 9 var person2 = new Person(); 10 person2.say(); // xiaoming
然而當包含引用類型值的屬性時,就會出現問題;
1 function Person(){} 2 Person.prototype.name="xiaoming"; 3 Person.prototype.age=18; 4 Person.prototype.eat=['蘋果','橘子']; 5 Person.prototype.say=function(){ 6 alert(this.name); 7 } 8 var person1=new Person(); 9 10 alert(person1.eat); // 蘋果 橘子 11 person1.eat.push("香蕉"); 12 var person2 = new Person(); 13 alert(person2.eat); // 蘋果 橘子 香蕉
可以看到,eat屬性是引用類型的值,當person1更改了eat數組,則在person2中也能反映出來,然而這並不是我們想要的結果。繼續看。
四、組合使用構造函數和原型模式
這種方式能極大解決單獨使用構造函數或者原型模式帶來的問題。這種方式是目前使用最廣泛的方法;組合使用,構造函數用來定義實例屬性,原型模式用來定義方法和共享屬性。這樣每個實例都會有屬於自己的實例屬性副本,而且同時又共享着對方法的引用,最大限度的節省了內存。
1 function Person(name,age){ 2 this.name=name; 3 this.age=age; 4 this.eat=['蘋果','橘子']; 5 } 6 Person.prototype.say=function(){ 7 alert(this.name); 8 } 9 var person1=new Person("xiaoming",18); 10 alert(person1.eat); // 蘋果 橘子 11 person1.eat.push("香蕉"); 12 var person2 = new Person(); 13 alert(person2.eat); // 蘋果 橘子