的繼承在很多書里面細(xì)致的分了很多種類型和實現(xiàn)方式,大體上就是兩種對象冒充、原型方式。這兩種方式各有優(yōu)點和缺陷,這里我給你先列舉出來,再從底層分析區(qū)別。我們看到了,在Js版本更新的過程中,為了更方便的執(zhí)行這種上下文this的切換以達(dá)到繼承或者更加廣義的目的,增加了call和apply函數(shù)。所以說盡管call和apply并不是僅僅為了繼承而新增的方法,但用它們可以模擬繼承。
javascript繼承有哪兩種形式
在很多書里,繼承分為很多類型和實現(xiàn)方法,一般是兩種:對象模擬和原型方法。這兩種方法各有利弊。這里我先給大家列舉一下,然后從底層分析一下區(qū)別:(1)對象冒充A(name){ this . name = name;這個。=(){alert(this.name+"sayHello!");};}B(name,id){ this . temp = A;this.temp(名稱);//相當(dāng)于newA();this.temp//防止超類A的屬性和方法將來被temp引用覆蓋this.id = id這個。=(ID){ alert(this . ID = = ID)};}構(gòu)造對象B時,調(diào)用temp相當(dāng)于啟動A的構(gòu)造函數(shù),注意這里上下文中的這個對象是B的實例,所以在執(zhí)行A的構(gòu)造函數(shù)腳本時,A的所有變量和方法都會賦給這個所指向的對象,也就是B的實例,從而達(dá)到B繼承A的屬性方法的目的,刪除臨時引用temp后, 是為了防止維護(hù)B中A的類對象(注意不是實例對象)的引用改變,因為改變temp會直接導(dǎo)致A類的結(jié)構(gòu)改變(注意不是A類的對象)。 我們可以看到,在Js版本更新的過程中,加入了call和apply函數(shù),是為了更方便的切換這個上下文,達(dá)到繼承或者更通用的目的。它們的原理是一樣的,只是參數(shù)的版本不同(一個變量是任意參數(shù),而一個參數(shù)集必須傳入數(shù)組)。這里以call為例說明call實現(xiàn)的對象假裝被繼承。Rect(width,){ this.width = width這個。=;this.area=(){this.width*this。;};}(width,,name){Rect.call(this,width,);this.name = namethis . show =(){ alert(this . name+" with area:"+this . area());}}關(guān)于調(diào)用方法,官方解釋:調(diào)用一個對象的方法,用另一個對象替換當(dāng)前對象。Call(,arg1,arg2…)這也是對象模擬的繼承。實際上,調(diào)用call方法時發(fā)生的也是上下文環(huán)境變量this的替換。在函數(shù)體中,這必須指向類對象的實例。但是,使用它作為上下文環(huán)境變量會調(diào)用Rect方法,即Rect類的構(gòu)造函數(shù)。所以當(dāng)Rect被調(diào)用時,它的賦值屬性和方法實際上是在一個新的對象上執(zhí)行的。所以雖然call和apply并不是僅僅針對繼承的新方法,但是它們可以模擬繼承。對象模仿繼承就是這樣的東西,它可以實現(xiàn)多重繼承,只需要重復(fù)賦值的過程。然而目前并沒有大規(guī)模使用。為什么?因為它有一個明顯的性能缺陷,所以有必要說一下OO的概念。我們說對象是成員+成員方法的集合。構(gòu)造對象實例時,這些實例只需要有自己的成員變量。成員方法只是一個對變量進(jìn)行操作的可執(zhí)行文本區(qū)域。不需要為每個實例復(fù)制這個區(qū)域,所有實例都可以共享?,F(xiàn)在回到Js對模擬對象的繼承,所有的成員方法都是為此而創(chuàng)建的,也就是所有的實例都會有一個成員方法的副本,這是對內(nèi)存資源的極度浪費。其他的缺陷,比如對象冒充變量,方法不能繼承域,就不用提了。我覺得前一個致命缺陷就夠了。但是我們還是要了解一下,尤其是父類的屬性和方法是如何繼承的原理,這對理解Js繼承非常重要。㈡原型。第二種類型的繼承是原型。所謂原型繼承,就是以某種方式使用或覆蓋,從而達(dá)到復(fù)制屬性方法的目的。實現(xiàn)的方式有很多種,不同的框架可能會有一些差異,但是如果把握住了原理,就沒有什么不懂的了??匆粋€例子(某種實現(xiàn)):(){ { this.name = " Mike這個。=(){alert("!");};}..=(){alert("你好!");};(){}.= new();關(guān)鍵是把prototype屬性賦給最后一句中類構(gòu)造的對象。在這里,作者解釋了如何將父類的屬性和方法復(fù)制到子類中。Js讀取一個對象的屬性時,總是先看自己域的屬性列表,如果有就返回;否則,它將讀取域(每個對象共享構(gòu)造該對象的類的域的所有屬性和方法),如果找到,它將返回。因為它可以指向其他對象,Js解釋器將遞歸地尋找域所指向的域