定義:能存放屬性的就是物件。
函式也是一個物件,物件也是物件,一個物件實體會有他的自己的屬性與繼承的屬性,可以檢查其 __proto__ 來找到他是被什麼函式生成的,該函式的 prototype 將會繼承到該物件上。
用來建構物件的建構子是一個函式,而函式也是物件,那最最最開始的函式是怎麼被建構出來呢? Object.prototype 在最開始時就存著一個物件,這個物件與其屬性就是根本。
怎麼說呢?,EC3 的物件都能參照到一個非標準的屬性 __proto__,只要檢查物件實體的 __proto__,就可以知道他是被哪一個建構子產生的,以下三個函式(物件)的 __proto__ 會是 Empty(){} ,所以根本還沒被建構子產生過。
(function(){}).__proto__ == Object.__proto__ == Function.__proto__
所以可以好好觀察 Object.prototype 物件內的屬性跟其本身。例如跟他同級的 Function 函式的 prototype 也是指到相同的實體。
Object.prototype == Function.prototype
或是把 Object 蓋掉看會怎麼發瘋…
Object = null; var obj = {}; console.log(obj);
prototype 屬性有一個 constructor 可以知道某個物件是被哪個函式建構出來,也代表他在被 new 的時候要呼叫過什麼函式,所以最原始的函式會有一個這樣的循環:
Object.prototype.constructor == Object ({}).constructor == Object Function.prototype.constructor == Function (function() {}).constructor == Function
所以如果自己設計的物件大概會長這個樣子。
function Mlwmlw() {} mlwmlw.prototype.constructor == mlwmlw mlwmlw.__proto__ == Object var mlwmlw = new Mlwmlw()
這樣我能在不呼叫 new Mlwmlw 的情況下來偽裝他是被什麼函式建構出來的,而且也繼承原本的屬性?
var mlwmlw = new (function() { var f = function() {} f.prototype = Mlwmlw.prototype; return f; })(); //偽裝他的建構子 mlwmlw.__proto__.constructor = Mlwmlw; //假裝執行建構子 mlwmlw.__proto__.constructor.apply(mlwmlw);
基於這些大概就可以持續的推論如何去繼承一個物件,或實作一些典型物件導向的一些特性。或者直接參考某些書的實作。
– Pro-JavaScript-Techniques by John-Resig
– Secrets of the JavaScript Ninja
– Pro JavaScript Design Patterns
或是一些經典小巧的實作
參考資源:
. http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
. http://www.slideshare.net/ferrantes/ecmascript-5-10575898