起初接觸JS時常見的簡單地建立單個對象的方式有下面三種:設計模式
以上三種方式在須要建立不少對象時會產生大量重複代碼。顯然須要更高效的方式,下面將介紹7種建立對象的方式安全
工廠模式正是源自設計模式中的工廠模式,其基本思想:函數
function createPerson(name, age) {
var obj = new Object()
obj.name = name
obj.age = age
obj.getName = function() {
console.log(this.name)
}
return obj
}
var person1 = createPerson("AAA", 23)
person1.getName() //AAA
var person2 = createPerson("BBB", 30)
person2.getName() //BBB
複製代碼
構造函數可建立特定類型的對象,相似Object和Array(實際上Object和Array自己就是構造函數)post
function Person(name, age) {
this.name = name
this.age = age
this.getName = function() {
console.log(this.name)
}
}
var person1 = new Person("AAA", 23)
person1.getName() //AAA
var person2 = new Person("BBB", 30)
person2.getName() //BBB
複製代碼
經過上面代碼咱們能夠看到構造函數模式:優化
構造函數其實也是個函數,只是能夠經過new調用來建立對象,固然也可做爲普通函數使用ui
//做爲普通函數使用
Person("CCC", 24)
Person.getName() //CCC
//在一個對象內調用
var obj = {}
Person.call(obj, "DDD", 25)
obj.getName() //DDD
複製代碼
console.log(person1 instanceof Object) //true
console.log(person1 instanceof Person) //true
複製代碼
console.log(person1.getName === person2.getName) //false
複製代碼
原型模式即經過原型對象來實現屬性和方法的共享,實例對象不會建立各自的副本this
要理解原型模式,建議先理解透徹JS原型的概念——推薦閱讀一張圖完全KO原型鏈(prototype,__proto__)spa
function Person() {
}
Person.prototype.name = "AAA"
Person.prototype.age = 23
Person.prototype.getName = function() {
console.log(this.name)
}
var person1 = new Person()
person1.getName() //AAA
var person2 = new Person()
person2.name = "BBB"
person2.getName() //BBB
console.log(person1.getName === person2.getName) //true
複製代碼
然而原型對象也存在缺陷——對於引用類型的屬性,各實例對象間指向同一個地址,某個對象修改了屬性,全部對象都會受到影響prototype
function Person() {
}
Person.prototype.arr = [1,2,3]
Person.prototype.getArr = function() {
console.log(this.arr)
}
var person1 = new Person()
person1.arr.push(4)
person1.getArr() //1,2,3,4
var person2 = new Person()
person2.getArr() //1,2,3,4
person1.arr.push(5)
person1.getArr() //1,2,3,4,5
person2.getArr() //1,2,3,4,5
複製代碼
組合模式即組合構造函數模式和原型模式,取兩者之長,構造函數模式用於定義實例的屬性,原型模式用於定義方法和共享的屬性設計
function Person(name, age) {
this.name = name
this.age = age
this.arr = [1,2,3]
}
Person.prototype = {
getName: function() {
console.log(this.name)
}
}
var person1 = new Person("AAA", 23)
person1.arr.push(4)
console.log(person1.arr) //1,2,3,4
person1.getName() //AAA
var person2 = new Person("BBB", 30)
console.log(person2.arr) //1,2,3
person2.getName() //BBB
複製代碼
剛說組合模式是承認度最高的一種模式,然而也有些美中不足——每建立一個實例對象,原型方法都被重複定義一次
動態原型模式正是解決這個問題,使用if語句,使得原型方法只初始化一次
function Person(name, age) {
this.name = name
this.age = age
//這裏只須要使用任何一個方式或屬性,不必定是getName,getAge也能夠
//只要保證if裏面的代碼只執行一次就行
if(typeof this.getName !== 'function') {
Person.prototype.getName = function() {
console.log(this.name)
}
Person.prototype.getAge = function() {
console.log(this.age)
}
}
}
var person = new Person("AAA", 23)
person.getName() //AAA
複製代碼
長得和工廠模式同樣,但調用方式和構造函數模式同樣的模式,經過new調用構造函數,本該返回一個實例對象,但return語句重寫了構造函數的返回值
function Person(name, age) {
var obj = new Object()
obj.name = name
obj.age = age
obj.getName = function() {
console.log(this.name)
}
return obj
}
var person = new Person("AAA", 23)
person.getName() //AAA
複製代碼
這種方式和工廠模式沒什麼不一樣,要說不一樣的就是經過new來調用,仍然存在工廠模式的沒法判別對象類型的問題
我的認爲這是一種多餘的方式,複雜而很差理解,也沒有什麼應用場景
先介紹一個概念——穩妥對象:
穩妥構造函數模式和工廠模式相似,但遵循穩妥對象的原則
function Person(name, age) {
var obj = new Object()
//getName是惟一讀取name的方式
obj.getName = function() {
console.log(name)
}
return obj
}
var person = Person("AAA", 23)
person.name = "BBB" //無效
person.getName() //AAA
複製代碼
工廠模式:解決了大量重複代碼的問題,但沒法判別對象類型
構造函數模式:實例對象又具體的類型,但每一個實例對象都有方法的副本,形成內存浪費
原型模式:可共享方法和屬性,但存在引用類型相互影響的問題
組合模式:取構造函數模式和原型模式之長 (最經常使用)
動態原型模式:優化了組合模式
寄生構造函數模式:相似工廠模式,只是經過new調用
穩妥構造函數模式:相似工廠模式,只是提高了安全性
但願本文對你有幫助,更多文章將持續更新……
感謝你的點贊和鼓勵
與本文相關的文章有: