js原型和原型鏈[轉]

來源:互聯網
上載者:User

標籤:spi   bsp   concepts   運行機制   top   null   一點   原型   task   

附上原文出處:http://hzjavaeyer.group.iteye.com/group/wiki/3086-JavaScript-core-concepts

 

一、概念:

原型對象:JavaScript對象是一個屬性的集合,另外有一個隱式的對象:原型對象。原型的值可以是一個對象或者null。一般的引擎實現中,JS對象會包含若干個隱藏屬性,對象的原型由這些隱藏屬性之一引用,我們在本文中討論時,將假定這個屬性的名稱為"__proto__"(事實上,SpiderMonkey內部正是使用了這個名稱,但是規範中並未做要求,因此這個名稱依賴於實現)。

原型鏈:由於原型對象本身也是對象,根據上邊的定義,它也有自己的原型,而它自己的原型對象又可以有自己的原型,這樣就組成了一條鏈,這個就是原型鏈,JavaScritp引擎在訪問對象的屬性時,如果在對象本身中沒有找到,則會去原型鏈中尋找,如果找到,直接傳回值,如果整個鏈都遍曆且沒有找到屬性,則返回undefined.原型鏈一般實現為一個鏈表,這樣就可以按照一定的順序來尋找。

 

二、執行個體:

No1:

 1 var base = { 2     name : "base", 3     getInfo : function(){ 4        return this.name; 5     } 6 } 7   8 var ext1 = { 9     id : 0,10     __proto__ : base11 }12  13 var ext2 = {14     id : 9,15     __proto__ : base16 }17  18 print(ext1.id);19 print(ext1.getInfo());20 print(ext2.id);21 print(ext2.getInfo());

結果為:

0
base
9
base

 

圖1:上例中對象的原型鏈

可以看到,當執行ext1.id時,引擎在ext1對象本身中就找到了id屬性,因此返回其值0,當執行ext1.getInfo時,ext1對象中沒有找到,因此在其原型對象base中尋找,找到之後,執行這個函數,得到輸出”base”。

 

我們將上例中的ext1對象稍加修改,為ext1對象加上name屬性:

NO2:

 1 var base = { 2     name : "base", 3     getInfo : function(){ 4        return this.name; 5     } 6 } 7   8 var ext1 = { 9     id : 0,10     name : "ext1",   11     __proto__ : base12 }13  14 print(ext1.id);15 print(ext1.getInfo());

可以得到:

0
ext1

這個運行效果同樣驗證了原型鏈的運行機制:從對象本身出發,沿著__proto__尋找,直到找到屬性名稱相同的值(沒有找到,則返回undefined)。

 

我們對上例再做一點修改,來更好的示範原型鏈的工作方式:

NO3:

 1 var base = { 2     name : "base", 3     getInfo : function(){ 4        return this.id + ":" + this.name; 5     } 6 } 7   8 var ext1 = { 9     id : 0,10     __proto__ : base11 }12  13 print(ext1.getInfo());

我們在getInfo函數中加入this.id,這個id在base對象中沒有定義。同時,刪掉了ext1對象中的name屬性,執行結果如下:

0:base

應該注意的是,getInfo函數中的this表示原始的對象,而並非原型對象。上例中的id屬性來自於ext1對象,而name來自於base對象。這個特性的機制在10.3小節再做討論。如果對象沒有顯式的聲明自己的”__proto__”屬性,這個值預設的設定為Object.prototype,而Object.prototype的”__proto__”屬性的值為”null”,標誌著原型鏈的終結。

 

三、構造器:

我們在來討論一下構造器,除了上邊提到的直接操作對象的__proto__屬性的指向以外,JavaScript還支援構造器形式的對象建立。構造器會自動的為新建立的對象設定原型對象,此時的原型對象通過構造器的prototype屬性來引用。

 

我們以例子來說明,將Task函數作為構造器,然後建立兩個執行個體task1, task2:

 1 function Task(id){ 2     this.id = id; 3 } 4   5 Task.prototype.status = "STOPPED"; 6 Task.prototype.execute = function(args){ 7     return "execute task_"+this.id+"["+this.status+"]:"+args; 8 } 9  10 var task1 = new Task(1);11 var task2 = new Task(2);12  13 task1.status = "ACTIVE";14 task2.status = "STARTING";15  16 print(task1.execute("task1"));17 print(task2.execute("task2"));

結果:

execute task_1[ACTIVE]:task1
execute task_2[STARTING]:task2

構造器會自動為task1,task2兩個對象設定原型對象Task.prototype,這個對象被Task(在此最為構造器)的prototype屬性引用,參看中的箭頭指向。

 

圖2:構造器方式的原型鏈

由於Task本身仍舊是函數,因此其”__proto__”屬性為Function.prototype, 而內建的函數原型對象的”__proto__”屬性則為Object.prototype對象。最後Obejct.prototype的”__proto__”值為null.

 

js原型和原型鏈[轉]

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.