工廠模式:
function createPerson(arguments){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){};
return o;
}
var person1 = createPerson(arguments);
解決創建多個相似對象的問題
缺點:
沒有解決對象識別問題
構造函數模式:
function Person(arguments){
this.name = name;
this.age = age;
this.sayName = function(){};
}
var person1 = new Person(arguments);
var person2 = new Person(arguments);
構造函數名大寫字母開頭
person1有constructor(構造函數)屬性,指向Person
person1.constructor == Person //true
person1 instanceof Object //true
person1 instanceof Person //true
構造函數當做普通函數使用,屬性和方法都添加給window
缺點:
每個方法在每個實例上都要重新創建一遍
person1.sayName == person2.sayName //false
原型模式:
每個函數都有一個prototype屬性,指向一個對象,這個對象可以包含特定類型所有實例共享的屬性和方法function Person(){
}
Person.prototype.name = 'myName';
Person.prototype.age = 66;
Person.prototype.sayName = function(){};
var person1 = new Person();
var person2 = new Person();
person1.name == person2.name //myName
person1.name = 'newName';
person1.name //newName(來自實例)
person2.name //myName (來自原型)
訪問屬性時,若沒有在實例中搜索到該屬性,就會在原型中搜索並返回該屬性
使用delete可以刪除實例中的屬性,此時再訪問該屬性則會返回原型中的屬性
delete person1.name;
person1.name //myName (來自原型)
原型與in操作符:
通過對象能夠訪問屬性時返回true(for-in返回能夠通過對象訪問的、可枚舉的屬性),無論是在實例中還是原型中原型模式的一些方法:
isPrototypeOf()Person.prototype.isPrototypeOf(person1) //true
Object.getPrototypeOf(person1) == Person.prototype //true
Object.getPrototypeOf(person1.name) //myName
hasOwnProperty() 檢測一個屬性是否存在於實例中
person1.name = 'newName';person1.hasOwnProperty('name'); //true
person2.hasOwnProperty('name'); //false
hasPrototypeProperty() 檢測一個屬性是否來自原型
hasPrototypeProperty(person1,'name'); //falsehasPrototypeProperty(person2,'name'); //true
Object.keys() 取得對象上所有可枚舉的實例屬性
Object.getOwnPropertyNames() 獲取所有實例屬性,無論是否可枚舉
原型的對象字面量寫法
function Person(){
}
Person.prototype = {
name:'myName',
age:66,
sayName:function(){}
};
這種寫法的constructor屬性不再指向Person,而是指向Object構造函數
var person3 = new Person();
person3 instanceof Person //true
person3 instanceof Object //true
person3.constructor == Person //false
person3.constructor == Object //true
缺點:
由於其共享的特性,對於包含引用類型值的屬性,實例無法有屬於自己的屬性
例如屬性中包含數組,若通過實例對象對數組進行修改,由於數組存在於prototype中,則會影響到所有的實例。
組合使用構造函數模式和原型模式(廣泛使用):
構造函數模式定義實例屬性,原型模式用於定義方法和共享的屬性function Person(arguments){
this.name = name;
this.age = age;
this.friends = ['a','b'];
}
Person.prototype = {
constructor:Person,
sayName:function(){}
};
動態原型模式:
function Person(arguments){
//屬性
this.name = name;
this.age = age;
//方法
if(typeof this.sayName != 'function'){
Person.prototype.sayName = function(){};
Person.prototype.otherFunction = function(){};
}
}
寄生構造函數模式:
function Person(arguments){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){};
return o;
}
var person1 = new Person(arguments);
除了使用new和構造函數,這個模式跟工廠模式是一樣的
例如要創建一個具有額外功能的Array,由於不能直接修改Array,可以這樣:
function SpecialArray(){
var sa = new Array();
sa.push.apply(sa,arguments); //使用apply是因爲push如果接收數組作爲參數,會將整個數組當做一個元素push
sa.newFunction = function(){};
}
var arr = new SpecialArray(arguments);
arr.newFunction();
穩妥構造函數模式(安全性考慮):
function Person(name,age){
var o = new Object();
o.sayName = function(){
return name;
}
return o;
}
var person1 = Person(name,age);
person1.sayName(); //除了使用sayName()方法之外沒其他辦法訪問到name的值