javascript原型繼承分析(prototype)
一直恪守的原則就是,要用一個東西,那麼一定要對這個東西非常的瞭解才可以,這樣在用的時候才能做到心裡有底、、或者說心裡有數。。。。接觸node.js也算是有一段的時間了,也拿它做了一些的東西,以前的一片文章算是分析了javascript的閉包原理,但是自己一直沒有將javascript的原型機制搞清楚,趁著現在比較的閒,靜下來將這一塊先搞定。。。。
首先我們來看一句比較奇怪的程式碼:
[javascript] view plaincopy- console.log(typeof Object);
這裡的輸出會比較的神奇:function
也就是說Object本身是一個function,那麼我們用如下的程式碼來看看這個Object這個function是怎麼定義的吧:
- console.log(Object.toString());
那麼這段程式碼的輸出是: function Object() { [native code] }
好吧,到這裡我們可以下結論Object是一個函式,而且這個函式的實現是javascript引擎內部的,對於這部分就無能為力了。。。
根據《javascript高階程式設計》以及《javascript語言精粹》的說法,可以畫出如下的圖形:
這裡因為Object是一個function,所以它有一個prototype屬性和一個name屬性,name的屬性的值就是“Object”,而prototype則指向了它的原型物件,而其原型物件中又包含一個constructor屬性指向當前的Object函式。。。
好了,接下來我們來看看按照物件字面量建立物件吧,程式碼:
[javascript] view plaincopy- var aa = {};
- aa.name = 'fjs';
上面通過字面量的方式建立了一個物件,並用aa來引用它,而且給了它一個name的屬性,這個時候可以用如下的圖來表示aa:
上圖的意思就是說剛剛建立的aa物件中有一個名字叫做__proto__的屬性指向了Object的prototype,而且這個屬性是預設新增上去的,這是一個內部的屬性,預設按照ECMA的規定,它是不可以訪問的,但是很多javascript引擎都通過__proto__這個名字來引用這個屬性。。
我們可以用如下的程式碼來驗證:
[javascript] view plaincopy- var aa = {};
- aa.name = 'fjs';
- console.log(aa.__proto__ === Object.prototype);
輸出的結果是true,那麼上面的圖形也就得到了驗證。。。
接下來我們來看看另外一種構造物件的方法,建構函式,先來看一個建構函式的定義:
[javascript] view plaincopy- function Fjs() {
- this.name = "fjs";
- }
這裡我們用另外一張圖來表示當前的情形:
這張圖形可以用如下的程式碼進行驗證:
[javascript] view plaincopy- function Fjs() {
- this.name = "fjs";
- }
- console.log(Fjs.prototype.constructor === Fjs);
- console.log(Fjs.prototype.__proto__ === Object.prototype);
上述的兩個輸出都是true,那麼上面的圖形也就得到了驗證,接下來我們來看看呼叫建構函式來建立物件都做了什麼事情,也就是如下程式碼:
[javascript] view plaincopy- function Fjs() {
- this.name = "fjs";
- }
- console.log(Fjs.prototype.constructor === Fjs);
- console.log(Fjs.prototype.__proto__ === Object.prototype);
- var fjs = new Fjs();
這種方式構造物件,其實javascript引擎是這麼搞的:
(1)建立一個新的物件
(2)將當前建構函式的作用域指向剛剛建立的新物件,也就是將建構函式的this指向剛剛建立的物件,而且要為這個物件的內部__proto__屬性賦值,用它指向當前建構函式的prototype屬性
(3)執行建構函式中的程式碼,也就是呼叫this,為剛剛建立的物件賦值
(4)返回該物件
那麼根據上述的步驟,我們又可以得到如下的圖形:
對於上述的圖形,我們可以用如下的程式碼來進行驗證:
[javascript] view plaincopy- function Fjs() {
- this.name = "fjs";
- }
- var fjs = new Fjs();
- console.log(fjs.__proto__ == Fjs.prototype);
輸出是true,那麼上述的圖形也就得到了驗證,其實從這裡也就能夠看到javascript所謂的原型鏈了。。。
到這裡為止應該算是對javascript的原型模式有了一定的瞭解了吧。。不至於像以前一樣裸奔了。。。