DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> 理解Javascript_05_原型繼承原理
理解Javascript_05_原型繼承原理
編輯:關於JavaScript     
prototype與[[prototype]]

在有面象對象基礎的前提下,來看一段代碼:
復制代碼 代碼如下:
//Animal構造函數
function Animal(name){
this.name = name;
}
//Animal原型對象
Animal.prototype = {
id:"Animal",
sleep:function(){
alert("sleep");
}
}

var dog = new Animal("旺才");
alert(dog.name);//旺才
alert(dog.id);//Animal
dog.sleep()//sleep

其對應的簡易內存分配結構圖:

現在讓我們來解釋一下這張內存圖的來龍去脈:

首先明確一點[[prototype]]與prototype並不是同一個東西。

  那先來看prototype,每一個函數對象都有一個顯示的prototype屬性,它代表了對象的原型,更明確的說是代表了由函數對象(構造函數)所創建出來的對象的原型。結合本例,Animal.prototype就是dog的原型,dog所引用的那個對象將從Animal.prototype所引用的對象那繼承屬性與方法。

  每個對象都有一個名為[[Prototype]]的內部屬性,指向於它所對應的原型對象。在本例中dog的[[prototype]]指向Animal.prototype,大家都知道,Animal.prototype也是一個對象,即然是一個對象,那它必然也有[[prototype]]屬性指向於它所對應的原型對象,由此便構成了一種鏈表的結構,這就是原型鏈的概念。額外要說的是:不同的JS引擎實現者可以將內部[[Prototype]]屬性命名為任何名字,並且設置它的可見性,前且只在JS引擎內部使用。雖然無法在JS代碼中訪問到內部[[Prototype]](FireFox中可以,名字為__proto__因為Mozilla將它公開了),但可以使用對象的 isPrototypeOf()方法進行測試,注意這個方法會在整個Prototype鏈上進行判斷。

注:關於函數對象的具體內容,將在後繼的博文中講解。

屬性訪問原則

使用obj.propName訪問一個對象的屬性時,按照下面的步驟進行處理(假設obj的內部[[Prototype]]屬性名為__proto__):
1. 如果obj存在propName屬性,返回屬性的值,否則
2. 如果obj.__proto__為null,返回undefined,否則
3. 返回obj.__proto__.propName
調用對象的方法跟訪問屬性搜索過程一樣,因為方法的函數對象就是對象的一個屬性值。
提示: 上面步驟中隱含了一個遞歸過程,步驟3中obj.__proto__是另外一個對象,同樣將采用1, 2, 3這樣的步驟來搜索propName屬性。

這就是基於Prototype的繼承和共享。其中object1的方法fn2來自object2,概念上即object2重寫了object3的方法fn2。
JavaScript對象應當都通過prototype鏈關聯起來,最頂層是Object,即對象都派生自Object類型。

結合是上面的理論,讓我們再來看一個更加復雜的示例,他明確的解釋了prototype、[[prototype]]、原型鏈以及屬性訪問的相關要點:
復制代碼 代碼如下:
//Animal構造函數
function Animal(name){
this.name = name;
}
//Animal原型對象
Animal.prototype = {
id:"Animal",
sleep:function(){
alert("sleep");
}
}

function Human(name,age){
Animal.call(this,name);
this.age = age;
}

Human.prototype = new Animal();
Human.prototype.id = "Human";

Human.prototype.say = function(){
alert("hello everyone,My name is "+this.name +",I'm "+this.age+" and I'm a "+this.id);
}

//Human相關調用
var jxl = new Human('笨蛋',25);
alert(jxl.name);//笨蛋
alert(jxl.id);//Human
jxl.say();//hello everyone,My name is 笨蛋,I'm 25 and I'm a Human

alert(Animal.prototype.isPrototypeOf(jxl));//true
alert(Object.prototype.isPrototypeOf(jxl));//true

根據上面的代碼,你能畫出相應的內存圖嗎?好,讓我們來看一下:

注:prototype的根為Object.prototype,對象Object.prototype的內部[[prototype]]屬性為null.
其實,這裡還有很多東西可以講,但在其原理都在這張圖上了,可試著調整一下代碼的次序,如將Human.prototype.id = "Human";放在Human.prototype = new Animal();的前面,看一下運行結果,解釋一下為什麼之類的,你可以學到很多。

我發現,通過內存來展現程序內部運行細節真的是太完美了!
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved