JavaScript中的幾個(gè)關(guān)鍵概念的理解-原型鏈的構(gòu)建
Javascript中所有function中都有一個(gè)prototype屬性,并且這個(gè)prototype屬性是一個(gè)object類(lèi)型的對(duì)象,所有由該function構(gòu)造出來(lái)的對(duì)象都具有這個(gè)prototype上的特性,也就是說(shuō)可以用構(gòu)造出來(lái)的對(duì)象直接訪問(wèn)prototype上的屬性和方法。
下面一段代碼演示prototype的使用方法:
function Staff(name) {
this.name = name;
}
Staff.prototype.say = function() {
alert(this.name + " say hello");
}
var staff1 = new Staff("hunter");
var staff2 = new Staff("dangjian");
staff1.say();
staff2.say();
運(yùn)行如上的程序,可知prototype上的屬性和方法可以通過(guò)創(chuàng)建的對(duì)象之間調(diào)用,更重要的是prototype中的屬性和方法是在同類(lèi)型的對(duì)象中是共享的
prototype另外一個(gè)常用的特性是通過(guò)prototype構(gòu)建對(duì)象的繼承關(guān)系,通過(guò)把基類(lèi)對(duì)象賦給子類(lèi)的prototype的方式可以模擬面向?qū)ο笾械睦^承關(guān)系,這就是大家經(jīng)常說(shuō)的JavaScript的面向?qū)ο髾C(jī)制。如下的代碼段演示了利用這一特性構(gòu)建對(duì)象的繼承關(guān)系:
function Staff(name) { // 基類(lèi)
this.name = name;
}
Staff.prototype.say = function() {
alert(this.name + " say hello");
}
function ManStaff(name, age) { // 子類(lèi)
this.name = name;
this.age = age;
}
ManStaff.prototype = new Staff(); // 建立繼承關(guān)系
var manStaff1 = new ManStaff("hunter", 22);
var manStaff2 = new ManStaff("dangjian", 32);
manStaff1.say();
manStaff2.say();
運(yùn)行代碼可知,ManStaff對(duì)象中具有了基類(lèi)Staff中的Say方法,這種繼承方式在JavaScript中是通過(guò)prototype鏈來(lái)實(shí)現(xiàn)的。大家可能熟悉以上的prototype用法,可是作為程序員,我們不光要知道其用法,我們更應(yīng)該理解其可是prototype的內(nèi)部機(jī)制。下面我們來(lái)分析prototype的原理以及prototype鏈的實(shí)現(xiàn)。
要理解prototype的機(jī)制就必須要了解JavaScript中function的創(chuàng)建方式。
當(dāng)代碼執(zhí)行到function Staff(name) {this.name = name;}時(shí),相當(dāng)于執(zhí)行var Staff = new Function(“name”, "this.name = name”)解釋器將使用預(yù)定義好的Function() constructor,來(lái)創(chuàng)建一個(gè)function類(lèi)型的object出來(lái),即Staff。
隨后給創(chuàng)建好的Staff對(duì)象添加__proto__屬性,并賦值為Function的構(gòu)造器的prototype,這一步是所有對(duì)象創(chuàng)建過(guò)程中都有的步驟,在執(zhí)行類(lèi)似var x = new X()方式是,都會(huì)把X的prototype賦值給x的__proto__,類(lèi)似如下的賦值:
Staff.__proto__ = Function.prototype;
接下來(lái)給Staff創(chuàng)建prototype屬性,這一步是創(chuàng)建function類(lèi)型的對(duì)象具有的步驟,創(chuàng)建的過(guò)程如下偽代碼:
var o = new Object();
o.constructor = Base;
Staff.prototype = o;
如上的分析我們可知,當(dāng)創(chuàng)建對(duì)象時(shí),會(huì)創(chuàng)建一個(gè)私有屬性__proto__,當(dāng)創(chuàng)建function是會(huì)創(chuàng)建一個(gè)prototype屬性。因?yàn)镾taff是一個(gè)function類(lèi)型的對(duì)象,所以會(huì)同時(shí)具有這兩個(gè)屬性。
這兩個(gè)屬性是構(gòu)建原型鏈的關(guān)鍵屬性。我們來(lái)分析執(zhí)行代碼 var staff1 = new Staff(“hunter”)時(shí),原型是如何傳遞的。
根據(jù)如上分析,staff1.__proto__ = Staff.prototype,而Staff.prototype又是一個(gè)由Object創(chuàng)建的對(duì)象,即Staff.prototype.__proto__ = Object.prototype,所以staff1.__proto__ .__proto__ 指向的是Object.prototype,即staff1.__proto__ .__proto__ == Object.prototype,這就是原型鏈,當(dāng)要讀取某個(gè)對(duì)象的屬性時(shí),JS首先找對(duì)象本身是否有這個(gè)屬性,如果沒(méi)有就會(huì)順著原型鏈一直尋找這個(gè)屬性。
知道了原型鏈的原理,那么就很容易根據(jù)這個(gè)原理來(lái)構(gòu)建Javascript中的對(duì)象繼承。
由如上的分析,我們可知原型鏈的頂端都是Object.prototype,這就意味著在構(gòu)建的繼承關(guān)系中Object是所有對(duì)象的基類(lèi),可以運(yùn)行如下的代碼驗(yàn)證。
Object.prototype.location = "China";
function Staff(name) { // 基類(lèi)
this.name = name;
}
Staff.prototype.say = function() {
alert(this.name + " say hello");
}
var ManStaff1 = new Staff("hunter");
var ManStaff2 = new Staff("dangjian");
alert(ManStaff1.location);
alert(ManStaff2.location);
運(yùn)行結(jié)果知道,Object是Staff的基類(lèi),那么要如何構(gòu)建一個(gè)Staff的子類(lèi)呢?
理解了上面函數(shù)的建立原理,我們很容易寫(xiě)出如下的代碼:
function Staff(name) { // 基類(lèi)
this.name = name;
}
Staff.prototype.say = function() {
alert(this.name + " say hello");
}
function ManStaff(name, age) { // 子類(lèi)
Staff.call(this,name);
this.age = age;
}
ManStaff.prototype = new Staff(); // 建立繼承關(guān)系
var ManStaff1 = new ManStaff("hunter", 22);
var ManStaff2 = new ManStaff("dangjian", 32);
ManStaff1.say();
ManStaff2.say();
建立繼承關(guān)系的就是這句:ManStaff.prototype = new Staff(); ,繼承關(guān)系推算如下:ManStaff1.__proto__ = =ManStaff.prototype, ManStaff.prototype.__proto__ = Staff.prototype, Staff.prototype.__proto__ == Object.prototype;則ManStaff1.__proto__.__proto__.__proto__ == Object.prototype。
javascript中的這種繼承關(guān)系比較傳統(tǒng)面向?qū)ο蟮睦^承關(guān)系更松散,構(gòu)建方式也比較難以理解,但是作為腳本語(yǔ)言,其功能已經(jīng)是非常強(qiáng)大了。
- 無(wú)廢話JavaScript教程(全集)
- 國(guó)外的為初學(xué)者寫(xiě)的JavaScript教程
- js原型鏈原理看圖說(shuō)明
- 基于JavaScript實(shí)現(xiàn)繼承機(jī)制之原型鏈(prototype chaining)的詳解
- 基于JavaScript實(shí)現(xiàn)繼承機(jī)制之構(gòu)造函數(shù)+原型鏈混合方式的使用詳解
- JS繼承--原型鏈繼承和類(lèi)式繼承
- 深入理解JavaScript系列(6) 強(qiáng)大的原型和原型鏈
- javascript學(xué)習(xí)筆記(九)javascript中的原型(prototype)及原型鏈的繼承方式
- JavaScript 原型鏈學(xué)習(xí)總結(jié)
- Javascript之旅 對(duì)象的原型鏈之由來(lái)
- Javascript學(xué)習(xí)筆記7 原型鏈的原理
- javascript prototype 原型鏈
- javascript教程之不完整的繼承(js原型鏈)
相關(guān)文章
JS如何使用正則表達(dá)式(match)截取括號(hào)中的文字和數(shù)字
正則表達(dá)式是一種用來(lái)匹配文本模式的工具,這篇文章主要給大家介紹了關(guān)于JS如何使用正則表達(dá)式(match)截取括號(hào)中文字和數(shù)字的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
JavaScript實(shí)現(xiàn)簡(jiǎn)易計(jì)算器小功能
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)易計(jì)算器小功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10
Javascript中With語(yǔ)句用法實(shí)例
這篇文章主要介紹了Javascript中With語(yǔ)句用法,實(shí)例分析了javascript中with語(yǔ)句的相關(guān)使用方法,類(lèi)似VB語(yǔ)句的用法,需要的朋友可以參考下2015-05-05
小程序按鈕避免多次調(diào)用接口和點(diǎn)擊方案實(shí)現(xiàn)(不用showLoading)
這篇文章主要介紹了小程序按鈕避免多次調(diào)用接口和點(diǎn)擊方案實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
javascript操作向表格中動(dòng)態(tài)加載數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了javascript操作向表格中動(dòng)態(tài)加載數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
js動(dòng)態(tài)生成Html元素實(shí)現(xiàn)Post操作(createElement)
這篇文章主要介紹了js動(dòng)態(tài)生成Html元素實(shí)現(xiàn)Post操作(createElement),需要的朋友可以參考下2015-09-09

