一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

Javascript繼承機制的設計思想

  作者: 阮一峰

  日期: 2011年6月 5日

  我一直很難理解Javascript語言的繼承機制。

  它沒有"子類"和"父類"的概念,也沒有"類"(class)和"實例"(instance)的區(qū)分,全靠一種很奇特的"原型鏈"(prototype chain)模式,來實現(xiàn)繼承。

  我花了很多時間,學習這個部分,還做了很多筆記。但是都屬于強行記憶,無法從根本上理解。

  直到昨天,我讀到法國程序員Vjeux的解釋,才恍然大悟,完全明白了Javascript為什么這樣設計。

  下面,我嘗試用自己的語言,來解釋它的設計思想。徹底說明白prototype對象到底是怎么回事。其實根本就沒那么復雜,真相非常簡單。

  一、從古代說起

  要理解Javascript的設計思想,必須從它的誕生說起。

  1994年,網(wǎng)景公司(NETscape)發(fā)布了Navigator瀏覽器0.9版。這是歷史上第一個比較成熟的網(wǎng)絡瀏覽器,轟動一時。但是,這個版本的瀏覽器只能用來瀏覽,不具備與訪問者互動的能力。比如,如果網(wǎng)頁上有一欄"用戶名"要求填寫,瀏覽器就無法判斷訪問者是否真的填寫了,只有讓服務器端判斷。如果沒有填寫,服務器端就返回錯誤,要求用戶重新填寫,這太浪費時間和服務器資源了。

  因此,網(wǎng)景公司急需一種網(wǎng)頁腳本語言,使得瀏覽器可以與網(wǎng)頁互動。工程師Brendan Eich負責開發(fā)這種新語言。他覺得,沒必要設計得很復雜,這種語言只要能夠完成一些簡單操作就夠了,比如判斷用戶有沒有填寫表單。

  1994年正是面向?qū)ο缶幊蹋╫bject-oriented programming)最興盛的時期,C++是當時最流行的語言,而Java語言的1.0版即將于第二年推出,Sun公司正在大肆造勢。

  Brendan Eich無疑受到了影響,Javascript里面所有的數(shù)據(jù)類型都是對象(object),這一點與Java非常相似。但是,他隨即就遇到了一個難題,到底要不要設計"繼承"機制呢?

  二、Brendan Eich的選擇

  如果真的是一種簡易的腳本語言,其實不需要有"繼承"機制。但是,Javascript里面都是對象,必須有一種機制,將所有對象聯(lián)系起來。所以,Brendan Eich最后還是設計了"繼承"。

  但是,他不打算引入"類"(class)的概念,因為一旦有了"類",Javascript就是一種完整的面向?qū)ο缶幊陶Z言了,這好像有點太正式了,而且增加了初學者的入門難度。

  他考慮到,C++和Java語言都使用new命令,生成實例。

  C++的寫法是:

ClassName *object = new ClassName(param);

  Java的寫法是:

Foo foo = new Foo();

  因此,他就把new命令引入了Javascript,用來從原型對象生成一個實例對象。但是,Javascript沒有"類",怎么來表示原型對象呢?

  這時,他想到C++和Java使用new命令時,都會調(diào)用"類"的構(gòu)造函數(shù)(constructor)。他就做了一個簡化的設計,在Javascript語言中,new命令后面跟的不是類,而是構(gòu)造函數(shù)。

  舉例來說,現(xiàn)在有一個叫做DOG的構(gòu)造函數(shù),表示狗對象的原型。

function DOG(name){

    this.name = name;

  }

  對這個構(gòu)造函數(shù)使用new,就會生成一個狗對象的實例。

var dogA = new DOG('大毛');

alert(dogA.name); // 大毛

  注意構(gòu)造函數(shù)中的this關鍵字,它就代表了新創(chuàng)建的實例對象。

  三、new運算符的缺點

  用構(gòu)造函數(shù)生成實例對象,有一個缺點,那就是無法共享屬性和方法。

  比如,在DOG對象的構(gòu)造函數(shù)中,設置一個實例對象的共有屬性species。

function DOG(name){

  this.name = name;

  this.species = '犬科';

}

  然后,生成兩個實例對象:

var dogA = new DOG('大毛');

var dogB = new DOG('二毛');

  這兩個對象的species屬性是獨立的,修改其中一個,不會影響到另一個。

dogA.species = '貓科';

alert(dogB.species); // 顯示"犬科",不受dogA的影響

  每一個實例對象,都有自己的屬性和方法的副本。這不僅無法做到數(shù)據(jù)共享,也是極大的資源浪費。

  四、prototype屬性的引入

  考慮到這一點,Brendan Eich決定為構(gòu)造函數(shù)設置一個prototype屬性。

  這個屬性包含一個對象(以下簡稱"prototype對象"),所有實例對象需要共享的屬性和方法,都放在這個對象里面;那些不需要共享的屬性和方法,就放在構(gòu)造函數(shù)里面。

  實例對象一旦創(chuàng)建,將自動引用prototype對象的屬性和方法。也就是說,實例對象的屬性和方法,分成兩種,一種是本地的,另一種是引用的。

  還是以DOG構(gòu)造函數(shù)為例,現(xiàn)在用prototype屬性進行改寫:

function DOG(name){

  this.name = name;

}

DOG.prototype = { species : '犬科' };


var dogA = new DOG('大毛');

var dogB = new DOG('二毛');


alert(dogA.species); // 犬科

alert(dogB.species); // 犬科

  現(xiàn)在,species屬性放在prototype對象里,是兩個實例對象共享的。只要修改了prototype對象,就會同時影響到兩個實例對象。

DOG.prototype.species = '貓科';

alert(dogA.species); // 貓科

alert(dogB.species); // 貓科

  五、總結(jié)

  由于所有的實例對象共享同一個prototype對象,那么從外界看起來,prototype對象就好像是實例對象的原型,而實例對象則好像"繼承"了prototype對象一樣。

  這就是Javascript繼承機制的設計思想。不知道我說清楚了沒有,繼承機制的具體應用方法,可以參考我寫的系列文章:

  * Javascript面向?qū)ο缶幊蹋ㄒ唬悍庋b》

  * Javascript面向?qū)ο缶幊蹋ǘ簶?gòu)造函數(shù)的繼承》

  * Javascript面向?qū)ο缶幊蹋ㄈ悍菢?gòu)造函數(shù)的繼承》

it知識庫Javascript繼承機制的設計思想,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 亚洲一区二区三区麻豆 | 欧美高清亚洲欧美一区h | 国产精品jizz视频 | jjzz亚洲亚洲女人 | 日韩一区二区三区视频在线观看 | 四虎影视在线影院4hutv | 国色天香网在线 | 在线观看色 | 看黄网站在线 | 99re6这里只有精品 | 91高清视频在线 | 91视频免费观看高清观看完整 | 国产三级网站在线观看 | 亚洲三级成人 | 看全色黄大色黄大片色黄看的 | 在线观看色网 | 91麻精品国产91久久久久 | 91福利在线看 | 97在线视频网站 | 欧美精品人爱a欧美精品 | 国产亚洲精品hd网站 | 久久国产精品-久久精品 | 国产真实伦正在播放 | 影音先锋国产资源 | 婷婷综合五月中文字幕欧美 | 黄色影片免费观看 | 无遮挡毛片a级武则天 | 色老板网站 | 五月丁香六月综合缴清无码 | 国产成人成人一区二区 | 国产精品第十页 | 中文字幕不卡一区 二区三区 | 久久国产美女免费观看精品 | 国产成人精品在线观看 | 精品无人区一区二区三区 | 亚洲第一视频在线播放 | 碰碰碰人人澡人人爱摸 | 中文字幕亚洲日韩无线码 | 久久精品道一区二区三区 | 一本一道久久综合狠狠老 | 成 人 黄 色视频免费播放 |