前言
起初接觸JS時常見的簡單地建立單個物件的方式有下面三種:
- 字面量,即var obj = {}
- new Object()
- Object.create()
以上三種方式在需要建立很多物件時會產生大量重複程式碼。顯然需要更高效的方式,下面將介紹7種建立物件的方式
1. 工廠模式
1.1介紹
工廠模式正是源自設計模式中的工廠模式,其基本思想:
- 既然建立物件數量多時產生了大量重複程式碼
- 那就建一座工廠,通過工廠來建立加工
- 再返回建立好的物件
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
複製程式碼
1.2 優劣分析
- 解決了複用性的問題
- 但無法判斷物件的型別(只知道是Objcet型別)
2. 建構函式模式
2.1 介紹
建構函式可建立特定型別的物件,類似Object和Array(實際上Object和Array本身就是建構函式)
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 Object()顯示建立物件
- 屬性和方法賦值給了this
- 無需return
2.2 建構函式也是函式
建構函式其實也是個函式,只是可以通過new呼叫來建立物件,當然也可作為普通函式使用
//作為普通函式使用
Person("CCC", 24)
Person.getName() //CCC
//在一個物件內呼叫
var obj = {}
Person.call(obj, "DDD", 25)
obj.getName() //DDD
複製程式碼
2.3 優劣分析
- 建構函式模式可以建立具體型別的物件
console.log(person1 instanceof Object) //true
console.log(person1 instanceof Person) //true
複製程式碼
- 然而,建構函式中的方法是通用的,但每個例項都建立了一份屬於自己的副本,造成記憶體浪費
console.log(person1.getName === person2.getName) //false
複製程式碼
3. 原型模式
3.1 介紹
原型模式即通過原型物件來實現屬性和方法的共享,例項物件不會建立各自的副本
要理解原型模式,建議先理解透徹JS原型的概念——推薦閱讀一張圖徹底KO原型鏈(prototype,__proto__)
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
複製程式碼
然而原型物件也存在缺陷——對於引用型別的屬性,各例項物件間指向同一個地址,某個物件修改了屬性,所有物件都會受到影響
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
複製程式碼
3.2 優劣分析
- 原型模式解決了屬性和方法的共享問題
- 但對於引用型別的屬性,各例項物件會相互影響
4. 組合模式
4.1介紹
組合模式即組合建構函式模式和原型模式,取二者之長,建構函式模式用於定義例項的屬性,原型模式用於定義方法和共享的屬性
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
複製程式碼
4.2 優劣分析
- 組合模式是使用最廣泛的一種模式,尤其在需要定義引用型別時
5. 動態原型模式
5.1 介紹
剛說組合模式是認可度最高的一種模式,然而也有些美中不足——每建立一個例項物件,原型方法都被重複定義一次
動態原型模式正是解決這個問題,使用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
複製程式碼
5.2 優劣分析
- 動態原型模式在組合模式的基礎上做了優化,可謂更加完美
6. 寄生建構函式模式
6.1 介紹
長得和工廠模式一樣,但呼叫方式和建構函式模式一樣的模式,通過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
複製程式碼
6.2 優劣分析
-
這種方式和工廠模式沒什麼不同,要說不同的就是通過new來呼叫,仍然存在工廠模式的無法判別物件型別的問題
-
個人認為這是一種多餘的方式,複雜而不好理解,也沒有什麼應用場景
7. 穩妥建構函式模式
7.1 介紹
先介紹一個概念——穩妥物件:
- 沒有公共屬性
- 不使用this
- 不使用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
複製程式碼
7.2 優劣分析
- 穩妥建構函式模式的特點就是安全性,適用於某些需要安全執行的環境
- 類似工廠模式,無法判別物件型別
8. 總結
-
工廠模式:解決了大量重複程式碼的問題,但無法判別物件型別
-
建構函式模式:例項物件又具體的型別,但每個例項物件都有方法的副本,造成記憶體浪費
-
原型模式:可共享方法和屬性,但存在引用型別相互影響的問題
-
組合模式:取建構函式模式和原型模式之長 (最常用)
-
動態原型模式:優化了組合模式
-
寄生建構函式模式:類似工廠模式,只是通過new呼叫
-
穩妥建構函式模式:類似工廠模式,只是提升了安全性
後記
希望本文對你有幫助,更多文章將持續更新……
感謝你的點贊和鼓勵
與本文相關的文章有: