<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    我的漫漫程序之旅

    專注于JavaWeb開發
    隨筆 - 39, 文章 - 310, 評論 - 411, 引用 - 0
    數據加載中……

    Javascript繼承

    Javascript繼承
    一直想對Javascript再次做一些總結,正好最近自己寫了一個小型Js UI庫,總結了一下Js的繼承機制,在網上也看了一些前輩們博客里的總結,感覺分析不是特別全面。這里僅僅是把自己的學習體會拿出來分享一下,希望對大家學習Javascript有所幫助。

    Javascript本身是從Perl語言的語法演變而來的,本質上是腳本語言,隨著版本的更新逐漸加入的對面向對象的模擬。我認為Js的面向對象模擬總體上做得還是不錯的,因為我們不能盲從任何一種理念,不能純粹的為了OOP而OOP,我們需要抓住的是面向對象的好處到底是什么?為了這些優點去OOP,才是最明智的選擇,所以說Js做得還不錯。

    Js的繼承在很多書里面細致的分了很多種類型和實現方式,大體上就是兩種:對象冒充、原型方式。這兩種方式各有優點和缺陷,這里我先列舉出來,再從底層分析區別:

    (一)對象冒充
    JScript code
    function A(name){ this.name = name; this.sayHello = function(){alert(this.name+” say Hello!”);}; } function B(name,id){ this.temp = A; this.temp(name); //相當于new A(); delete this.temp; //防止在以后通過temp引用覆蓋超類A的屬性和方法 this.id = id; this.checkId = function(ID){alert(this.id==ID)}; }


    當構造對象B的時候,調用temp相當于啟動A的構造函數,注意這里的上下文環境中的this對象是B的實例,所以在執行A構造函數腳本時,所有A的變量和方法都會賦值給this所指的對象,即B的實例,這樣子就達到B繼承了A的屬性方法的目的。之后刪除臨時引用temp,是防止維護B中對A的類對象(注意不是實例對象)的引用更改,因為更改temp會直接導致類A(注意不是類A的對象)結構的變化。

    我們看到了,在Js版本更新的過程中,為了更方便的執行這種上下文this的切換以達到繼承或者更加廣義的目的,增加了call和apply函數。它們的原理是一樣的,只是參數不同的版本罷了(一個可變任意參數,一個必須傳入數組作為參數集合)。這里就以call為例子,解釋一下用call實現的對象冒充繼承。

    JScript code
    function Rect(width, height){ this.width = width; this.height = height; this.area = function(){return this.width*this.height;}; } function myRect(width, height, name){ Rect .call(this,width,height); this.name = name; this.show = function(){ alert(this.name+with area:”+this.area()); } }


    關于Call方法,官方解釋:調用一個對象的一個方法,以另一個對象替換當前對象。
    call (thisOb,arg1, arg2…)

    這也是一種對象冒充的繼承,其實在call方法調用的時候發生的事情也是上下文環境變量this的替換,在myRect函數體中this肯定是指向類myRect對象的實例了,然而用這個this作為上下文環境變量調用名字叫Rect方法,即類Rect的構造函數。于是此時調用Rect時候對this的賦值屬性和方法都實際上是對一個myRect的對象進行。所以說盡管call和apply并不是僅僅為了繼承而新增的方法,但用它們可以模擬繼承。

    對象冒充繼承就是這么一回事,它可以實現多重繼承,只要重復做這一套賦值的流程就可以了。不過目前真正大規模使用得并不多,為什么呢?因為它有一個明顯的性能缺陷,這就要說道OO的概念了,我們說對象是成員+成員方法的集合,構造對象實例的時候,這些實例只需要擁有各自的成員變量就可以了,成員方法只是一段對變量操作的可執行文本區域而已,這段區域不用為每個實例而復制一份,所有的實例都可以共享。現在回到Js利用對象冒充模擬的繼承里,所有的成員方法都是針對this而創建的,也就是所所有的實例都會擁有一份成員方法的副本,這是對內存資源的一種極度浪費。其它的缺陷比如說對象冒充無法繼承prototype域的變量和方法就不用提了,筆者認為前一個致命缺陷就已經足夠。不過,我們還是需要理解它,特別是父類的屬性和方法是如何繼承下來的原理,對于理解Js繼承很重要。

    (二)原型方式
    第二種繼承方式是原型方式,所謂原型方式的繼承,是指利用了prototype或者說以某種方式覆蓋了prototype,從而達到屬性方法復制的目的。其實現方式有很多中,可能不同框架多少會有一點區別,但是我們把握住原理,就不會有任何不理解的地方了。看一個例子(某一種實現):

    JScript code
    function Person(){ this.name = “Mike”; this.sayGoodbye = function(){alert(“GoodBye!”);}; } Person.prototype.sayHello = function(){alert(”Hello!”);}; function Student(){} Student.prototype = new Person();


    關鍵是對最后一句Student原型屬性賦值為Person類構造的對象,這里筆者解釋一下父類的屬性和方法是如何copy到子類上的。Js對象在讀取某個對象屬性的時候,總是先查看自身域的屬性列表,如果有就返回否則去讀取prototype域(每個對象共享構造對象的類的prototype域所有屬性和方法),如果找到就返回,由于prototype可以指向別的對象,所以Js解釋器會遞歸的去查找prototype域指向對象的prototype域,直到prototype為本身,查找變成了一種循環,就停止,此時還沒找到就成undefined了。

    這樣看來,最后一句發生的效果就是將父類所有屬性和方法連接到子類的prototype域上,這樣子類就繼承了父類所有的屬性和方法,包括name、sayGoodbye和sayHello。這里與其把最后一句看成一種賦值,不如理解成一種指向關系更好一點。這種原型繼承的缺陷也相當明顯,就是繼承時父類的構造函數時不能帶參數,因為對子類prototype域的修改是在聲明子類對象之后才能進行,用子類構造函數的參數去初始化父類屬性是無法實現的,如下所示:

    JScript code
    function Person(name){ this.name = name; } function Student(name,id){ this.id = id; } Student.prototype = new Person(this.name);



    兩種繼承方式已經講完了,如果我們理解了兩種方式下子類如何把父類的屬性和方法“抓取”下來,就可以自由組合各自的利弊,來實現真正合理的Js繼承。下面是個人總結的一種綜合方式:

    JScript code
    function Person(name){ this.name = name; } Person.prototype.sayHello = function(){alert(this.name+“say Hello!”);}; function Student(name,id){ Person.call(this,name); this.id = id; } Student.prototype = new Person(); Student.prototype.show = function(){ alert(“Name is:”+ this.name+” and Id is:”+this.id); }


    總結就是利用對象冒充機制的call方法把父類的屬性給抓取下來,而成員方法盡量寫進被所有對象實例共享的prototype域中,以防止方法副本重復創建。然后子類繼承父類prototype域來抓取下來所有的方法。如想徹底理清這些調用鏈的關系,推薦大家多關注Js中prototype的constructor和對象的constructor屬性,這里就不多說了。

    posted on 2009-07-09 13:13 々上善若水々 閱讀(1403) 評論(0)  編輯  收藏 所屬分類: JavaScript

    主站蜘蛛池模板: 无码国产精品一区二区免费虚拟VR| 国产一区二区三区免费观在线| 波多野结衣免费在线观看| 亚洲伊人久久大香线蕉苏妲己| 国产1024精品视频专区免费| 亚洲人成在线影院| 四虎成人精品永久免费AV| 久久久亚洲欧洲日产国码二区| 99久久精品免费视频| 亚洲熟妇av一区二区三区下载| h视频在线免费看| 亚洲粉嫩美白在线| 免费高清在线影片一区| 国产精品亚洲五月天高清| 亚洲日本va午夜中文字幕久久| jizz18免费视频| 亚洲精品免费在线观看| 黄网站色在线视频免费观看| 亚洲中文无码亚洲人成影院| 国产免费午夜a无码v视频| 特级毛片aaaa免费观看| 香蕉蕉亚亚洲aav综合| 我们的2018在线观看免费高清| 亚洲国产精品日韩av不卡在线| 亚洲VA综合VA国产产VA中| a毛片在线看片免费| 亚洲成AV人综合在线观看| 国产大片91精品免费观看男同| 一级毛片a免费播放王色| 久久精品国产精品亚洲蜜月| 永久免费AV无码国产网站| 免费大片黄在线观看| 亚洲αv在线精品糸列| 青青在线久青草免费观看| 看免费毛片天天看| 亚洲国产精品不卡在线电影| 啦啦啦手机完整免费高清观看| 成人a毛片视频免费看| 亚洲最新黄色网址| 亚洲国产精品尤物YW在线观看| 222www免费视频|