欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

javascript繼承,javascript類繼承

js繼承之組合繼承

組合繼承,指的是將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合在一塊,從而發(fā)揮二者之長的一種繼承模式。

網(wǎng)站建設(shè)公司,為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及定制網(wǎng)站建設(shè)服務(wù),專注于成都企業(yè)網(wǎng)站建設(shè),高端網(wǎng)頁制作,對效果圖設(shè)計等多個行業(yè)擁有豐富的網(wǎng)站建設(shè)經(jīng)驗的網(wǎng)站建設(shè)公司。專業(yè)網(wǎng)站設(shè)計,網(wǎng)站優(yōu)化推廣哪家好,專業(yè)成都網(wǎng)站推廣優(yōu)化,H5建站,響應(yīng)式網(wǎng)站。

紅寶書是這樣說的,其思路是使用原型鏈實現(xiàn)對原型屬性和方法的繼承,通過借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承,這樣,即通過在原型上定義方法實現(xiàn)了函數(shù)復(fù)用,又能保證每個實例都有自己的屬性。

下面我們看一個組合繼承的例子,沒有女朋友我們就new一個女朋友

組合繼承避免了原型鏈和借用構(gòu)造函數(shù)的缺陷,融合了他們的優(yōu)點,So,組合繼承成為了JavaScript中最常用的繼承模式。

javascript什么是繼承

Javascript繼承 一直想對Javascript再次做一些總結(jié),正好最近自己寫了一個小型Js UI庫,總結(jié)了一下Js的繼承機制,在網(wǎng)上也看了一些前輩們博客里的總結(jié),感覺分析不是特別全面。這里僅僅是把自己的學習體會拿出來分享一下,希望對大家學習Javascript有所幫助。 Javascript本身是從Perl語言的語法演變而來的,本質(zhì)上是腳本語言,隨著版本的更新逐漸加入的對面向?qū)ο蟮哪M。我認為Js的面向?qū)ο竽M總體上做得還是不錯的,因為我們不能盲從任何一種理念,不能純粹的為了OOP而OOP,我們需要抓住的是面向?qū)ο蟮暮锰幍降资鞘裁矗繛榱诉@些優(yōu)點去OOP,才是最明智的選擇,所以說Js做得還不錯。 Js的繼承在很多書里面細致的分了很多種類型和實現(xiàn)方式,大體上就是兩種:對象冒充、原型方式。這兩種方式各有優(yōu)點和缺陷,這里我先列舉出來,再從底層分析區(qū)別: (一)對象冒充

JScript code

functionA(name){

this.name = name;

this.sayHello = function(){alert(this.name+” say Hello!”);};

}

functionB(name,id){

this.temp = A;

this.temp(name); //相當于new A();

deletethis.temp; //防止在以后通過temp引用覆蓋超類A的屬性和方法

this.id = id;

this.checkId = function(ID){alert(this.id==ID)};

}

當構(gòu)造對象B的時候,調(diào)用temp相當于啟動A的構(gòu)造函數(shù),注意這里的上下文環(huán)境中的this對象是B的實例,所以在執(zhí)行A構(gòu)造函數(shù)腳本時,所有A的變量和方法都會賦值給this所指的對象,即B的實例,這樣子就達到B繼承了A的屬性方法的目的。之后刪除臨時引用temp,是防止維護B中對A的類對象(注意不是實例對象)的引用更改,因為更改temp會直接導(dǎo)致類A(注意不是類A的對象)結(jié)構(gòu)的變化。 我們看到了,在Js版本更新的過程中,為了更方便的執(zhí)行這種上下文this的切換以達到繼承或者更加廣義的目的,增加了call和apply函數(shù)。它們的原理是一樣的,只是參數(shù)不同的版本罷了(一個可變?nèi)我鈪?shù),一個必須傳入數(shù)組作為參數(shù)集合)。這里就以call為例子,解釋一下用call實現(xiàn)的對象冒充繼承。

JScript code

functionRect(width, height){

this.width = width;

this.height = height;

this.area = function(){returnthis.width*this.height;};

}

functionmyRect(width, height, name){

Rect .call(this,width,height);

this.name = name;

this.show = function(){

alert(this.name+” with area:”+this.area());

}

}

關(guān)于Call方法,官方解釋:調(diào)用一個對象的一個方法,以另一個對象替換當前對象。 call (thisOb,arg1, arg2…) 這也是一種對象冒充的繼承,其實在call方法調(diào)用的時候發(fā)生的事情也是上下文環(huán)境變量this的替換,在myRect函數(shù)體中this肯定是指向類myRect對象的實例了,然而用這個this作為上下文環(huán)境變量調(diào)用名字叫Rect方法,即類Rect的構(gòu)造函數(shù)。于是此時調(diào)用Rect時候?qū)his的賦值屬性和方法都實際上是對一個myRect的對象進行。所以說盡管call和apply并不是僅僅為了繼承而新增的方法,但用它們可以模擬繼承。 對象冒充繼承就是這么一回事,它可以實現(xiàn)多重繼承,只要重復(fù)做這一套賦值的流程就可以了。不過目前真正大規(guī)模使用得并不多,為什么呢?因為它有一個明顯的性能缺陷,這就要說道OO的概念了,我們說對象是成員+成員方法的集合,構(gòu)造對象實例的時候,這些實例只需要擁有各自的成員變量就可以了,成員方法只是一段對變量操作的可執(zhí)行文本區(qū)域而已,這段區(qū)域不用為每個實例而復(fù)制一份,所有的實例都可以共享。現(xiàn)在回到Js利用對象冒充模擬的繼承里,所有的成員方法都是針對this而創(chuàng)建的,也就是所所有的實例都會擁有一份成員方法的副本,這是對內(nèi)存資源的一種極度浪費。其它的缺陷比如說對象冒充無法繼承prototype域的變量和方法就不用提了,筆者認為前一個致命缺陷就已經(jīng)足夠。不過,我們還是需要理解它,特別是父類的屬性和方法是如何繼承下來的原理,對于理解Js繼承很重要。 (二)原型方式 第二種繼承方式是原型方式,所謂原型方式的繼承,是指利用了prototype或者說以某種方式覆蓋了prototype,從而達到屬性方法復(fù)制的目的。其實現(xiàn)方式有很多中,可能不同框架多少會有一點區(qū)別,但是我們把握住原理,就不會有任何不理解的地方了。看一個例子(某一種實現(xiàn)):

JScript code

functionPerson(){

this.name = “Mike”;

this.sayGoodbye = function(){alert(“GoodBye!”);};

}

Person.prototype.sayHello = function(){alert(”Hello!”);};

functionStudent(){}

Student.prototype = newPerson();

關(guān)鍵是對最后一句Student原型屬性賦值為Person類構(gòu)造的對象,這里筆者解釋一下父類的屬性和方法是如何copy到子類上的。Js對象在讀取某個對象屬性的時候,總是先查看自身域的屬性列表,如果有就返回否則去讀取prototype域(每個對象共享構(gòu)造對象的類的prototype域所有屬性和方法),如果找到就返回,由于prototype可以指向別的對象,所以Js解釋器會遞歸的去查找prototype域指向?qū)ο蟮膒rototype域,直到prototype為本身,查找變成了一種循環(huán),就停止,此時還沒找到就成undefined了。 這樣看來,最后一句發(fā)生的效果就是將父類所有屬性和方法連接到子類的prototype域上,這樣子類就繼承了父類所有的屬性和方法,包括name、sayGoodbye和sayHello。這里與其把最后一句看成一種賦值,不如理解成一種指向關(guān)系更好一點。這種原型繼承的缺陷也相當明顯,就是繼承時父類的構(gòu)造函數(shù)時不能帶參數(shù),因為對子類prototype域的修改是在聲明子類對象之后才能進行,用子類構(gòu)造函數(shù)的參數(shù)去初始化父類屬性是無法實現(xiàn)的,如下所示:

JScript code

functionPerson(name){

this.name = name;

}

functionStudent(name,id){

this.id = id;

}

Student.prototype = newPerson(this.name);

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

JScript code

functionPerson(name){

this.name = name;

}

Person.prototype.sayHello = function(){alert(this.name+“say Hello!”);};

functionStudent(name,id){

Person.call(this,name);

this.id = id;

}

Student.prototype = newPerson();

Student.prototype.show = function(){

alert(“Name is:”+ this.name+” and Id is:”+this.id);

}

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

在JavaScript中,繼承可以用四種方式實現(xiàn),

1、對象冒充

感覺這種方式利用了js中類和函數(shù)的模糊性,同是function關(guān)鍵字申明方法,既可以說他是函數(shù),也可以說他是類,js太靈活了,下面的例子說明下:

function ClassA(sColor){ this.color=sColor; this.sayColor=function(){ alert(this.color); } }function ClassB(sColor){ this.newMethod=ClassA;//把ClassA方法賦給newMethod. this.newMethod();//調(diào)用newMethod. delete this.newMethod;}

ClassB執(zhí)行ClassA方法便相當于繼承了ClassA,在調(diào)用完畢后要刪除newMethod,因為后續(xù)添加的屬性和方法如果和超類同名,就會覆蓋超類的相關(guān)屬性和方法。

利用這種繼承方式可以實現(xiàn)多重繼承,如:

多重繼承 function ClassD(sColor){ this.newMethod=ClassA;//把ClassA方法賦給newMethod, this.newMethod();//調(diào)用newMethod delete this.newMethod; this.newMethod=ClassB; this.newMethod(); delete this.newMethod;}

利用這種多重繼承方法有個弊端,如果ClassA和ClassB具有相同的屬性和方法,ClassB有較高的優(yōu)先級。

2、call方法和apply方法

由于第一種方法很流行,所以ECMAScript便function對象加入兩個新方法,call()和apply(),這兩中方法很相似,只有在傳參方面有所不同,

call()方法的第一個參數(shù)用作this的對象,例如:

Call方法 function ClassB(sColor,sName){ ClassA.call(this,sColor); this.name=sName; this.sayName=function(){ alert(this.name);

}

}

call方法還是調(diào)用了ClassA()方法,利用this傳遞進去ClassB,為ClassB初始化,他僅僅是調(diào)用了ClassA()方法而已,如果你在ClassA之外為ClassA添加了方法(例如利用原型法),是不能繼承到ClassB的。

call()方法的第一個參數(shù)必須是this,可以有第二個,第三個,第四個....參數(shù)。

apply()方法與call()方法不同的是,將二個,第三個,第四個....參數(shù)用一個數(shù)組傳遞。例如:

function ClassB(sColor,sName,sSex){ var arr=new Arry(sColor,sName,sSex); ClassA.apply(this,arr);//傳遞數(shù)組 this.name=sName; this.sayName=function(){ alert(this.name); }}

可以將arguments作為參數(shù)傳遞給apply,但是ClassB的參數(shù)順序必須和ClassA一致。

3.原型鏈

利用prototype實現(xiàn)繼承,prototype對象是個模板,要實例的對象都是以這個模板為基礎(chǔ),它的任何屬性和方法都被傳遞給那個類的所有實例,原型鏈利用這種功能來實現(xiàn)繼承機制。

如果利用原型方式實現(xiàn)繼承,實例如下:

原型鏈 function ClassA(){ } ClassA.prototype.color="red"; ClassA.prototype.sayColor=function(){ alert(this.color); } function ClassB(){ } ClassB.prototype=newClassA();

通過原型鏈,ClassA的所有屬性和方法傳遞給了ClassB,用prototype的確是方便很多。

注意的是調(diào)用ClassA的構(gòu)造函數(shù)是,沒有給它傳遞參數(shù),這是在原型鏈中的標準做法。要確保構(gòu)造函數(shù)沒有任何參數(shù)。如果構(gòu)造函數(shù)中有參數(shù)的話會怎樣呢?那樣便不能完全的繼承,只能繼承父類通過prototype初始的屬性和方法,在構(gòu)造函數(shù)中初始的屬性和方法便不會繼承。

與對象冒充相似,子類的所有屬性和方法都必須出現(xiàn)在prototype屬性被賦值之后,因為在它之前賦值的所有方法都會被刪除。為什么呢?因為prototype屬性被替換成了新的對象,原始對象的prototype屬性以不復(fù)存在了,例如:

Code function ClassB(){ } ClassB.prototype=new ClassA(); ClassB.prototype.name=""; ClassB.prototype.sayName=function(){ alert(this.name);

}

原型鏈的弊端是不支持多重繼承,需要記住的是,原型鏈會用另一個類型的對象重寫類的prototype屬性。

3.混合方式

使用原型鏈方法實現(xiàn)繼承非常的方便,問題是不能夠使用帶參數(shù)的構(gòu)造函數(shù),通常使用構(gòu)造函數(shù)來定義屬性是最常見而且是最好的方式,要怎么做才可以好呢?

將對象冒充和原型鏈法結(jié)合起來使用,用對象冒充繼承構(gòu)造函數(shù)的屬性,用原型鏈繼承prototype對象的方法,用這種方式重寫前面的例子,代碼如下:

function ClassA(sColor){ this.color=sColor; } ClassA.prototype.sayColor=function(){ alert(this.color); }; function ClassB(sColor,sName){ ClassA.call(this,sColor); this.name=sName; } ClassB.prototype=new ClassA(); ClassB.prototype.sayName=function(){ alert(this.name); }; function show() { var a=new ClassA("red"); var b=new ClassB("blue","lhy"); a.sayColor();//輸出red b.sayColor();//輸出blue b.sayName();//輸出lhy }

在此例子中,繼承由兩種方式實現(xiàn),既使用了call方法,又使用了原型鏈,在構(gòu)造函數(shù)中,用對象冒充繼承ClassA類的sColor屬性,在接下來的代碼中利用原型鏈繼承ClassA的方法,這樣結(jié)合了對象冒充方法彌補了原型鏈法不能使用帶參的構(gòu)造函數(shù)的缺陷。

怎么體現(xiàn)javascript的繼承關(guān)系

js繼承的概念

js里常用的如下兩種繼承方式:

原型鏈繼承(對象間的繼承)

類式繼承(a href=";tn=44039180_cprfenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYn10zuADLujP9nAczPyFb0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPHnLPH03nHDd"target="_blank" class="baidu-highlight"構(gòu)造函數(shù)/a間的繼承)

由于js不像java那樣是真正a href=";tn=44039180_cprfenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYn10zuADLujP9nAczPyFb0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPHnLPH03nHDd" target="_blank" class="baidu-highlight"面向?qū)ο?a的語言,js是基于對象的,它沒有類的概念。所以,要想實現(xiàn)繼承,可以用js的原型prototype機制或者用apply和call方法去實現(xiàn)

在a href=";tn=44039180_cprfenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYn10zuADLujP9nAczPyFb0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPHnLPH03nHDd" target="_blank" class="baidu-highlight"面向?qū)ο?a的語言中,我們使用類來創(chuàng)建一個自定義對象。然而js中所有事物都是對象,那么用什么辦法來創(chuàng)建自定義對象呢?這就需要用到j(luò)s的原型:

我們可以簡單的把prototype看做是一個模版,新創(chuàng)建的自定義對象都是這個模版(prototype)的一個拷貝 (實際上不是拷貝而是鏈接,只不過這種鏈接是不可見,新實例化的對象內(nèi)部有一個看不見的__Proto__指針,指向原型對象)。

js可以通過a href=";tn=44039180_cprfenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYn10zuADLujP9nAczPyFb0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPHnLPH03nHDd"target="_blank" class="baidu-highlight"構(gòu)造函數(shù)/a和原型的方式模擬實現(xiàn)類的功能。 另外,js類式繼承的實現(xiàn)也是依靠原型鏈來實現(xiàn)的。

原型式繼承與類式繼承

類式繼承是在子類型a href=";tn=44039180_cprfenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYn10zuADLujP9nAczPyFb0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPHnLPH03nHDd" target="_blank" class="baidu-highlight"構(gòu)造函數(shù)/a的內(nèi)部調(diào)用超類型的構(gòu)造函數(shù)。

嚴格的類式繼承并不是很常見,一般都是組合著用:

function Super(){

this.colors=["red","blue"];

}

function Sub(){

Super.call(this);

}

原型式繼承是借助已有的對象創(chuàng)建新的對象,將子類的原型指向父類,就相當于加入了父類這條原型鏈

原型鏈繼承

為了讓子類繼承父類的屬性(也包括方法),首先需要定義一個構(gòu)造函數(shù)。然后,將父類的新實例賦值給構(gòu)造函數(shù)的原型。代碼如下:

script

function Parent(){

this.name = 'mike';

}

function Child(){

this.age = 12;

}

Child.prototype = new Parent();//Child繼承Parent,通過原型,形成鏈條

var test = new Child();

alert(test.age);

alert(test.name);//得到被繼承的屬性

//繼續(xù)原型鏈繼承

function Brother(){ //brother構(gòu)造

this.weight = 60;

}

Brother.prototype = new Child();//繼續(xù)原型鏈繼承

var brother = new Brother();

alert(brother.name);//繼承了Parent和Child,彈出mike

alert(brother.age);//彈出12

/script

以上原型鏈繼承還缺少一環(huán),那就是Object,所有的構(gòu)造函數(shù)都繼承自O(shè)bject。而繼承Object是自動完成的,并不需要我們自己手動繼承,那么他們的a href=";tn=44039180_cprfenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYn10zuADLujP9nAczPyFb0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPHnLPH03nHDd" target="_blank" class="baidu-highlight"從屬關(guān)系/a是怎樣的呢?

確定原型和實例的關(guān)系

可以通過兩種方式來確定原型和實例之間的關(guān)系。操作符instanceof和isPrototypeof()方法:

alert(brother instanceof Object)//true

alert(test instanceof Brother);//false,test 是brother的超類

alert(brother instanceof Child);//true

alert(brother instanceof Parent);//true

只要是原型鏈中出現(xiàn)過的原型,都可以說是該原型鏈派生的實例的原型,因此,isPrototypeof()方法也會返回true

在js中,被繼承的函數(shù)稱為超類型(父類,基類也行),繼承的函數(shù)稱為子類型(子類,派生類)。使用原型繼承主要由兩個問題:

一是字面量重寫原型會中斷關(guān)系,使用引用類型的原型,并且子類型還無法給超類型傳遞參數(shù)。

偽類解決引用共享和超類型無法傳參的問題,我們可以采用“借用構(gòu)造函數(shù)”技術(shù)

借用構(gòu)造函數(shù)(類式繼承)

script

function Parent(age){

this.name = ['mike','jack','smith'];

this.age = age;

}

function Child(age){

Parent.call(this,age);

}

var test = new Child(21);

alert(test.age);//21

alert(test.name);//mike,jack,smith

test.name.push('bill');

alert(test.name);//mike,jack,smith,bill

/script

借用構(gòu)造函數(shù)雖然解決了剛才兩種問題,但沒有原型,則復(fù)用無從談起,所以我們需要原型鏈+借用構(gòu)造函數(shù)的模式,這種模式稱為組合繼承

組合繼承

script

function Parent(age){

this.name = ['mike','jack','smith'];

this.age = age;

}

Parent.prototype.run = function () {

return this.name + ' are both' + this.age;

};

function Child(age){

Parent.call(this,age);//對象冒充,給超類型傳參

}

Child.prototype = new Parent();//原型鏈繼承

var test = new Child(21);//寫new Parent(21)也行

alert(test.run());//mike,jack,smith are both21

/script

組合式繼承是比較常用的一種繼承方法,其背后的思路是 使用原型鏈實現(xiàn)對原型屬性和方法的繼承,而通過借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承。這樣,既通過在原型上定義方法實現(xiàn)了函數(shù)復(fù)用,又保證每個實例都有它自己的屬性。

call()的用法:調(diào)用一個對象的一個方法,以另一個對象替換當前對象。

call([thisObj[,arg1[, arg2[, [,.argN]]]]])

原型式繼承

這種繼承借助原型并基于已有的對象創(chuàng)建新對象,同時還不用創(chuàng)建自定義類型的方式稱為原型式繼承

script

function obj(o){

function F(){}

F.prototype = o;

return new F();

}

var box = {

name : 'trigkit4',

arr : ['brother','sister','baba']

};

var b1 = obj(box);

alert(b1.name);//trigkit4

b1.name = 'mike';

alert(b1.name);//mike

alert(b1.arr);//brother,sister,baba

b1.arr.push('parents');

alert(b1.arr);//brother,sister,baba,parents

var b2 = obj(box);

alert(b2.name);//trigkit4

alert(b2.arr);//brother,sister,baba,parents

/script

原型式繼承首先在obj()函數(shù)內(nèi)部創(chuàng)建一個臨時性的構(gòu)造函數(shù) ,然后將傳入的對象作為這個構(gòu)造函數(shù)的原型,最后返回這個臨時類型的一個新實例。

寄生式繼承

這種繼承方式是把原型式+a href=";tn=44039180_cprfenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYn10zuADLujP9nAczPyFb0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPHnLPH03nHDd" target="_blank" class="baidu-highlight"工廠模式/a結(jié)合起來,目的是為了封裝創(chuàng)建的過程。

script

function create(o){

var f= obj(o);

f.run = function () {

return this.arr;//同樣,會共享引用

};

return f;

}

/script

組合式繼承的小問題

組合式繼承是js最常用的繼承模式,但組合繼承的超類型在使用過程中會被調(diào)用兩次;一次是創(chuàng)建子類型的時候,另一次是在子類型構(gòu)造函數(shù)的內(nèi)部

script

function Parent(name){

this.name = name;

this.arr = ['哥哥','妹妹','父母'];

}

Parent.prototype.run = function () {

return this.name;

};

function Child(name,age){

Parent.call(this,age);//第二次調(diào)用

this.age = age;

}

Child.prototype = new Parent();//第一次調(diào)用

/script

以上代碼是之前的組合繼承,那么寄生組合繼承,解決了兩次調(diào)用的問題。

寄生組合式繼承

script

function obj(o){

function F(){}

F.prototype = o;

return new F();

}

function create(parent,test){

var f = obj(parent.prototype);//創(chuàng)建對象

f.constructor = test;//增強對象

}

function Parent(name){

this.name = name;

this.arr = ['brother','sister','parents'];

}

Parent.prototype.run = function () {

return this.name;

};

function Child(name,age){

Parent.call(this,name);

this.age =age;

}

inheritPrototype(Parent,Child);//通過這里實現(xiàn)繼承

var test = new Child('trigkit4',21);

test.arr.push('nephew');

alert(test.arr);//

alert(test.run());//只共享了方法

var test2 = new Child('jack',22);

alert(test2.arr);//引用問題解決

/script

call和apply

全局函數(shù)apply和call可以用來改變函數(shù)中this的指向,如下:

// 定義一個全局函數(shù)

function foo() {

console.log(this.fruit);

}

// 定義一個全局變量

var fruit = "apple";

// 自定義一個對象

var pack = {

fruit: "orange"

};

// 等價于window.foo();

foo.apply(window); // "apple",此時this等于window

// 此時foo中的this === pack

foo.apply(pack); // "orange"

js原型鏈和繼承的理解

Object() Function() Array() 等等都為構(gòu)造函數(shù)。

Js 面向?qū)ο笈c傳統(tǒng)oop 有些不同,語法較高級 語法糖封裝。

This 為指針。指向this作用域的調(diào)用者

1.原型繼承鏈頂端為Object 。Js函數(shù)是對象

2.當讀取對象中的屬性時,先去實例本身中搜索,如搜索不到則去指向的原型中搜索

1.原型的存在意義在于實現(xiàn)繼承共享,是在構(gòu)造函數(shù)中定義的一個成員對象,在下次實例化時不需要在構(gòu)造函數(shù)中定義成員 就可實現(xiàn)實例共享方法屬性。

例子:通常為。 構(gòu)造函數(shù).prototype.xxx=我想實現(xiàn)實例繼承的東西 -》 new 構(gòu)造函數(shù) -》新實例a對象.原型指針指向構(gòu)造函數(shù)的xxx對象(引用類型)

例子:Array 不等于 Array() 原因 Array為一個函數(shù),而Array()為一個構(gòu)造函數(shù)調(diào)用語句,故Array擁有prototype對象用于實例的共享繼承,Array()產(chǎn)生一個實例 故只能擁有prototype對象的私有指針 proto

2.在使用原型繼承時 不能使用字面量 構(gòu)造函數(shù).prototype={} 的方式重寫原型對象 。因為會導(dǎo)致該原型對象的constructor屬性被重寫,在生成的實例中導(dǎo)致constructor指向Object并且會切斷之前原型對象的聯(lián)系,破壞原型鏈。

3.JavaScript 主要通過原型鏈實現(xiàn)繼承。原型鏈的構(gòu)建是通過將一個類型的實例賦值給另一個構(gòu)造函數(shù)的原型實現(xiàn)的

例子:

xxx實例. proto -》function xxx()構(gòu)造函數(shù).prototype對象故xxx. proto === xxx.prototype

xxx.prototype. proto -》Object.prototype因為所有對象都為Object函數(shù)構(gòu)造來的。故xxx.prototype. proto ===Object.prototype。

Object.prototype. proto 為原型鏈頂端 proto 定義了尚未使用所以為null故Object.prototype. proto ===null約定俗成。

instanceof 用來判斷某實例是否為某構(gòu)造函數(shù)的實例

isPrototypeOf 用于判斷某實例是否擁有某構(gòu)造函數(shù)的原型對象指針

1.原型模式有忽略構(gòu)造函數(shù)定義初始值步驟及原型中操作引用類型的缺點。

所以需要組合使用 構(gòu)造函數(shù)模式+原型模式 來創(chuàng)建實例。在構(gòu)造函數(shù)中定義實例的屬性,而需共享的方法就定義在原型對象中。

繼承:在子構(gòu)造函數(shù)中調(diào)用 父.call(this, name); 實現(xiàn)構(gòu)造函數(shù)之間的屬性繼承。使用 子.prototype = new 父(); 子.prototype.constructor = 子;實現(xiàn)方法的繼承。

2.如要在生產(chǎn)環(huán)境下的構(gòu)造函數(shù)新增方法(如Array) 需要使用一個類似于工廠函數(shù)的寄生構(gòu)造函數(shù)模式 在構(gòu)造函數(shù)中返回一個修改后的對象

新聞名稱:javascript繼承,javascript類繼承
瀏覽路徑:http://www.chinadenli.net/article12/dsdeggc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃營銷型網(wǎng)站建設(shè)網(wǎng)站設(shè)計公司品牌網(wǎng)站設(shè)計軟件開發(fā)動態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作