欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入淺析javascript繼承體系

 更新時間:2017年10月23日 09:27:32   作者:嗜血無恒  
這篇文章主要介紹了javascript繼承體系的相關(guān)資料,需要的朋友可以參考下

最近做web項目,接觸了jquery等框架,雖然使用方便,但是還是想學(xué)習(xí)下Javascript,今天分享下最近對js原型繼承的理解,不足之處歡迎指正。

一、構(gòu)造器的原型屬性與原型對象

  剛接觸js時通常依樣畫瓢,用函數(shù)new一個實例,也不知道其原因,只聽說js中函數(shù)即對象。原來js中沒有采用Java等語言中的類繼承體系,而是使用原型對象(prototype)實現(xiàn)繼承體系,具體說是利用“構(gòu)造器”實現(xiàn)類的功能。

首先解釋下原型繼承中的兩個重要概念:原型屬性、原型對象(實例)。

就js對象系統(tǒng)而言,創(chuàng)建的每個函數(shù)(構(gòu)造器)都有一個prototype原型屬性,同時,通過構(gòu)造器創(chuàng)建的每個對象實例也包含一個_proto_屬性,prototype和_proto_屬性是一個指針,指向原型對象。普通函數(shù)與構(gòu)造函數(shù)的唯一區(qū)別就是,其原型屬性prototype是不是一個有意義的值。

原型屬性prototype所指向的原型是一個對象實例(Object instance)。具體如下圖所示,若構(gòu)造器Animal()有一個原型對象B,則由該構(gòu)造器創(chuàng)建的實例都必然復(fù)制于B。即:Animal()的實例a1的_proto_屬性也會指向原型對象B。因此,實例a1能夠繼承B的所有屬性、方法和其他性質(zhì)。

圖1 js對象實例化實現(xiàn)

二、空的對象

在javascript中,“空的對象”是整個原型繼承體系的根基,是所有對象的基礎(chǔ)。介紹“空的對象”之前,必須先介紹下“空對象(null)”。

空對象null

  null不是“空的對象”,作為javascript中的一個保留字,其含義是:

 ?。?)屬于對象類型

  (2)對象是空值

作為一個對象類型,可以使用for…in去列舉它,但是作為一個空值,null沒有任何方法和屬性(包括constructor、_proto_等屬性),因此列舉不到任何內(nèi)容。如下例所示:  

var num=0;
  for(var propertyName in null)
  {
  num++;
  }

  Alert(num);//顯示值為0

最重要的一點是null沒有原型,它并不是自O(shè)bject()構(gòu)造器(或其子類)實例化而來,對其進行instanceof 運算會返回false。

  2.“空的對象”

  “空的對象”是指一個標(biāo)準(zhǔn)的、通過Object()構(gòu)造的對象實例。例如:

obj=new Object();或 obj={};

  “空的對象”具有“對象”的一切特性,因此可以存取toString()、valueof等預(yù)定義的屬性和方法。

  3.“空的對象”與null的關(guān)系

   如下圖2中紅線所示路徑,當(dāng)通過”O(jiān)bject.prototype._proto_”獲取Object原型對象的-proto-屬性時,將會得到”null”,由于null對象沒有任何屬性,也就是說”O(jiān)bject {}”

  原型對象就是原型鏈的終點了。

圖2 js類繼承體系

三、Javascript繼承的實現(xiàn)以及原型鏈維護

(1)繼承的實現(xiàn)

  第一節(jié)說過javascript中類繼承是通過修改構(gòu)造函數(shù)的原型屬性prototype實現(xiàn)的。如下代碼所示:

function Animal() {
this.name = 'Animal';
};
function Dog() {
};
  Dog.prototype = new Animal();
var d = new Dog();
console.log(d.name);//'Animal'

  通過創(chuàng)建一個Animal類型的實例并將其賦值給構(gòu)造函數(shù)Dog()的prototype屬性,從而實現(xiàn)類型繼承,即Animal是Dog的父類。這樣Dog類型的實例d也能訪問Animal類型的name屬性。

(2)原型鏈

JS對象繼承體系中有兩種原型鏈:“內(nèi)部原型鏈”和“構(gòu)造器原型鏈”。如圖3所示,黑色箭頭指示路徑是通過構(gòu)造函數(shù)的prototype屬性保持的“構(gòu)造器原型鏈”。紅色箭頭指示路徑是通過對象實例的_proto_屬性保持的“內(nèi)部原型鏈”。

圖3 原型鏈

(3)原型鏈維護

圖3說明構(gòu)造器通過顯示的prototype構(gòu)建了一個原型鏈,而對象實例也通過_ proto _屬性構(gòu)建了一個原型鏈。由于_ proto _是一個不可訪問的內(nèi)部屬性(Chrome中可以查看對象_ proto _屬性的值,但不可以修改),因此無法從子類(Dog)的實例dog1開始訪問整個原型鏈。因此,我們需要從圖3中的“內(nèi)部原型鏈”和“構(gòu)造器原型鏈”中找到一個連接點,使得實例不能訪問obj._proto_的情況下通過構(gòu)造器訪問內(nèi)部原型鏈(將兩種原型鏈串聯(lián)起來)。

若要從子類的實例開始訪問整個原型鏈,需要使用實例的constructor屬性維護原型鏈。

其實,JavaScript已經(jīng)為構(gòu)造器維護了原型屬性,根據(jù)如下測試代碼,當(dāng)我們自定義一個構(gòu)造器時,其原型對象是一個Object()類型的實例,但是其原型對象的constructor屬性默認(rèn)總是指向構(gòu)造器自身,而非指向其父類Object。如圖4中構(gòu)造器實例中藍色框中的constructor屬性,該constructor屬性繼承自原型對象,因此可以得出一個自定義的構(gòu)造器產(chǎn)生的實例,其constructor屬性默認(rèn)總是指向該構(gòu)造器。

function Animal() {
};
var a = new Animal();
console.log(Animal.prototype);//Object(){}
console.log(Animal.prototype.constructor === Animal);//true//true

  

圖4

  因此,在_proto_屬性不可訪問時,可通過a1.constructor.prototype獲取實例a1的原型對象。然而,當(dāng)我們自定義一個構(gòu)造函數(shù)Dog(),并且手動指定其prototype屬性值為Animal,即指定Dog的父類為Animal。此時訪問d1.constructor值為Animal,而不是Dog;由圖5可以看出,Dog的原型對象和dog分別由Animal()和Dog()兩個不同的構(gòu)造器產(chǎn)生,然而他們的constructor屬性指向了相同的構(gòu)造器(Animal),這樣就與使用constructor屬性串聯(lián)兩種原型鏈的設(shè)想沖突了。

圖5

  是構(gòu)造器出問題還是原型出了問題?圖5可以看出,原型繼承要求的“復(fù)制行為”已經(jīng)正確實現(xiàn),能夠從子類實例中訪問原型對象屬性,問題是在給子類構(gòu)造器Dog()賦予一個原型對象時應(yīng)該“修正”該原型對象的構(gòu)造屬性值(constructor)。ECMAScript 3標(biāo)準(zhǔn)提供的方法是:保持原型的構(gòu)造器屬性,在子類構(gòu)造器中初始化其實例對象的構(gòu)造屬性。代碼如下: 

function Dog () {
  //初始化constructor屬性
   this.constructor=Dog; //或 this.constructor=arguments.callee;
  };
  Dog.prototype = new Animal();//賦予原型對象,實現(xiàn)繼承

圖6

對constructor屬性“修正”后效果如圖6所示,在子類構(gòu)造器Dog中初始化其實例對象的constructor屬性后,Dog的實例對象的constructor都指向Dog,而Dog的原型對象的constructor仍然指向父類型構(gòu)造器Animal。這樣就可以實現(xiàn)利用constructor屬性串聯(lián)起原型鏈,可以從子類實例開始回溯整個原型鏈。

總結(jié)

以上所述是小編給大家介紹的javascript繼承體系的相關(guān)知識,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 詳解能在多種前端框架下使用的表格控件

    詳解能在多種前端框架下使用的表格控件

    表格控件是我們在開發(fā)中經(jīng)常要用到的控件。有沒有能夠在多種前端控件下都能使用的表格控件?最近研究發(fā)現(xiàn)Wijmo中的FlexGrid是一款不錯的表格控件,它能支持很多主流的框架。這里主要介紹在純JavaScript和AngularJS下FlexGrid的使用。
    2017-01-01
  • javascript 子窗體父窗體相互傳值方法

    javascript 子窗體父窗體相互傳值方法

    javascript 子窗體父窗體相互傳值方法,一般都是用window.open函數(shù),下面腳本之家給出具體的代碼。
    2010-05-05
  • JavaScript的console命令使用實例

    JavaScript的console命令使用實例

    這篇文章主要介紹了javascript的console命令使用實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • 利用Javascript仿Excel的數(shù)據(jù)透視分析功能

    利用Javascript仿Excel的數(shù)據(jù)透視分析功能

    這篇文章給大家介紹了如何利用Javascript實現(xiàn)類似Excel的數(shù)據(jù)透視分析功能,感興趣的朋友們可以參考借鑒,下面來一起看看吧。
    2016-09-09
  • js一般方法改寫成面向?qū)ο蠓椒ǖ臒o限級折疊菜單示例代碼

    js一般方法改寫成面向?qū)ο蠓椒ǖ臒o限級折疊菜單示例代碼

    本例是應(yīng)用別人的例子,原來那位老兄是用一般方法寫成的無限級折疊菜單,通過了一些簡化修改,將原來的例子改成了面向?qū)ο蟮姆绞?/div> 2013-07-07
  • 如何利用JavaScript讀取excel文件并繪制echarts圖形

    如何利用JavaScript讀取excel文件并繪制echarts圖形

    這篇文章主要介紹了如何利用JavaScript讀取excel文件并繪制echarts圖形,文章通過excel財務(wù)報表,并且需要根據(jù)這張excel表繪制成各種echarts圖形,需要了解更多詳情的小伙伴可以參考一下文章內(nèi)內(nèi)容
    2022-05-05
  • 夯基礎(chǔ)之手撕javascript繼承詳解

    夯基礎(chǔ)之手撕javascript繼承詳解

    這篇文章主要給大家介紹了關(guān)于手撕javascript繼承的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • JS制作可以選項卡切換的年歷

    JS制作可以選項卡切換的年歷

    這篇文章主要為大家分享了JS制作類似于選項卡切換的年歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • JS利用?clip-path?實現(xiàn)動態(tài)區(qū)域裁剪功能

    JS利用?clip-path?實現(xiàn)動態(tài)區(qū)域裁剪功能

    這篇文章主要介紹了JS利用?clip-path?實現(xiàn)動態(tài)區(qū)域裁剪功能,文中主要通過使用 box-shadow 實現(xiàn),代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • javascript實現(xiàn) 在光標(biāo)處插入指定內(nèi)容

    javascript實現(xiàn) 在光標(biāo)處插入指定內(nèi)容

    javascript實現(xiàn) 在光標(biāo)處插入指定內(nèi)容...
    2007-05-05

最新評論