先知道個keyword:
__proto__: javascript自己定義的變數,用來實現inheritance效果,有點類似像link listnode的概念,連結其他的 prototype
javascript記憶體管理的配置:
class儲存在 global底下- class的
prototype放置在heap (即class底下的各種variable和function) instance(ex var b = new B()) 的b儲存在 callstack(記憶體RAM裡面)
slogan:在自己的scope裡面找不到要的函式或變數就跟自己的__proto__要!
繼承範例:
1 | var Car = function(){ |
benz.numberOfWheels() 有此方法
每次呼叫Car.apply(this, arguments)時"複製"到子類別的物件上
初始化物件時較慢,在run time想要動態改變numberOfWheels()的實作時
無法影響已經創建的子類別或父類別instances.
以下為初始化較有效率的寫法:
1 | var Car = function () { |
numberOfWheels該方法已經被掛在 Car.prototype上,
所以並不像Car.apply上直接複製一份給子class們,而是子class去共用Car.prototype.numberOfWheels 這個方法。
- 優點:節省初始化的時間和提升效率
- 缺點:這種寫法不支援存取private property
javascript 類別、prototype以及reference中的__proto__所指向的關係示意圖:
圖片作者: Ben大大

假設 B class extend A;
let b = new B(); // b.__proto__ = B.prototype
let a = new A(); // a.__proto__ = A.prototype
let o = new Object(); o.__proto__ = Object.prototype
//對應到圖片左邊的b、a、o.
(先從圖片最左上角開始看
那 var b = new B();
b想要使用繼承A的 getValue() 函式,
那麼就得先找自己的 b.prototype 沒有的話 找 b.__proto__ = B.prototype
若b.__proto__也沒有的話(即B.prototype)也沒有,
那麼找 B.prototype.__proto__ == A.prototype
在A.prototype就會找到getValue()的函式!
如果又沒找到,那就最後找A.prototype.__proto__ == Object.prototype
若沒有那就找 Object.prototype.__proto__ == null 即找無該函式,compile告知發生錯誤);
Prototype inheritance 的好處
- Suitable in loosely typed environments, no need to define explicit types.
- Makes it incredibly easy to implement
singleton pattern(compare JavaScript and Java in this regard, and you’ll know what I am talking about).
(why? 因為prototype inheritance提供??? 請看補充二)
- Provides ways of applying a method of an object in the context of a different object, adding and replacing methods dynamically from an object etc. (things which are not possible in a strongly typed languages).
Prototype inheritance的壞處
- No easy way of implementing private variables. Its possible to implement private vars using Crockford’s wizardry using
closures, but its definitely not as trivial as using private variables in say Java or C#.
(因為__prpto__會指向prototype的所有成員!故無法像class inheritance那樣避免繼承到有private關鍵字的變數,故得用closure手法來避免繼承到_private變數)
Reference:
prototype based vs. class based inheritance
補充ㄧ:Function.prototype.apply
fun.apply(thisArg, [argsArray])
// 將一連串參數用array包起來:[argsArray],丟給fun函式處理
範例:
1 | function theFunction(name, profession) { |
補充二:用Closure實作Singleton模式
閉包觀念連結:==> 閉包是什麼??
先看範例程式碼
1 | var UniverseN; |
可以看出若利用了Prototype inheritance的特性,,將IIFE函式掛在UniverseN.prototype.IIFE上,使得之後宣告的物件不會在複製一份IIFE出來出來,讓IIFE只跑一次!
這樣就可以達成一個class (UniverseN) 只能宣告一次的物件 (uni9)。 如果在宣告出 uni10,他們都還是指向同一樣的instance(uni9.__proto__ == uni10__proto__)
Reference:
JavaScript Design Pattern - Singleton 單體模式