JavaScript 深入之建立物件的多種方式以及優缺點

發表於2017-05-28

寫在前面

這篇文章講解建立物件的各種方式,以及優缺點。

但是注意:

這篇文章更像是筆記,因為《JavaScript高階程式設計》寫得真是太好了!

1. 工廠模式

缺點:物件無法識別,因為所有的例項都指向一個原型

2. 建構函式模式

優點:例項可以識別為一個特定的型別

缺點:每次建立例項時,每個方法都要被建立一次

2.1 建構函式模式優化

優點:解決了每個方法都要被重新建立的問題

缺點:這叫啥封裝……

3. 原型模式

優點:方法不會重新建立

缺點:1. 所有的屬性和方法都共享 2. 不能初始化引數

3.1 原型模式優化

優點:封裝性好了一點

缺點:重寫了原型,丟失了constructor屬性

3.2 原型模式優化

優點:例項可以通過constructor屬性找到所屬建構函式

缺點:原型模式該有的缺點還是有

4. 組合模式

建構函式模式與原型模式雙劍合璧。

優點:該共享的共享,該私有的私有,使用最廣泛的方式

缺點:有的人就是希望全部都寫在一起,即更好的封裝性

4.1 動態原型模式

注意:使用動態原型模式時,不能用物件字面量重寫原型

解釋下為什麼:

為了解釋這個問題,假設開始執行var person1 = new Person('kevin')

如果對 new 和 apply 的底層執行過程不是很熟悉,可以閱讀底部相關連結中的文章。

我們回顧下 new 的實現步驟:

  1. 首先新建一個物件
  2. 然後將物件的原型指向 Person.prototype
  3. 然後 Person.apply(obj)
  4. 返回這個物件

注意這個時候,回顧下 apply 的實現步驟,會執行 obj.Person 方法,這個時候就會執行 if 語句裡的內容,注意建構函式的 prototype 屬性指向了例項的原型,使用字面量方式直接覆蓋 Person.prototype,並不會更改例項的原型的值,person1 依然是指向了以前的原型,而不是 Person.prototype。而之前的原型是沒有 getName 方法的,所以就報錯了!

如果你就是想用字面量方式寫程式碼,可以嘗試下這種:

5.1 寄生建構函式模式

寄生建構函式模式,我個人認為應該這樣讀:

寄生-建構函式-模式,也就是說寄生在建構函式的一種方法。

也就是說打著建構函式的幌子掛羊頭賣狗肉,你看建立的例項使用 instanceof 都無法指向建構函式!

這樣方法可以在特殊情況下使用。比如我們想建立一個具有額外方法的特殊陣列,但是又不想直接修改Array建構函式,我們可以這樣寫:

你會發現,其實所謂的寄生建構函式模式就是比工廠模式在建立物件的時候,多使用了一個new,實際上兩者的結果是一樣的。

但是作者可能是希望能像使用普通 Array 一樣使用 SpecialArray,雖然把 SpecialArray 當成函式也一樣能用,但是這並不是作者的本意,也變得不優雅。

在可以使用其他模式的情況下,不要使用這種模式。

但是值得一提的是,上面例子中的迴圈:

可以替換成:

5.2 穩妥建構函式模式

所謂穩妥物件,指的是沒有公共屬性,而且其方法也不引用 this 的物件。

與寄生建構函式模式有兩點不同:

  1. 新建立的例項方法不引用 this
  2. 不使用 new 操作符呼叫建構函式

穩妥物件最適合在一些安全的環境中。

穩妥建構函式模式也跟工廠模式一樣,無法識別物件所屬型別。

深入系列

JavaScript深入系列目錄地址:https://github.com/mqyqingfeng/Blog

JavaScript深入系列預計寫十五篇左右,旨在幫大家捋順JavaScript底層知識,重點講解如原型、作用域、執行上下文、變數物件、this、閉包、按值傳遞、call、apply、bind、new、繼承等難點概念。

如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。如果喜歡或者有所啟發,歡迎star,對作者也是一種鼓勵。

  1. JavaScirpt 深入之從原型到原型鏈
  2. JavaScript 深入之詞法作用域和動態作用域
  3. JavaScript 深入之執行上下文棧
  4. JavaScript 深入之變數物件
  5. JavaScript 深入之作用域鏈
  6. JavaScript 深入之從 ECMAScript 規範解讀 this
  7. JavaScript 深入之執行上下文
  8. JavaScript 深入之閉包
  9. JavaScript 深入之引數按值傳遞
  10. JavaScript 深入之call和apply的模擬實現
  11. JavaScript 深入之bind的模擬實現
  12. JavaScript 深入之new的模擬實現
  13. JavaScript 深入之類陣列物件與 arguments

相關文章