js繼承是用來(lái)干啥的:
首先說(shuō)js沒(méi)有真正的跟其他面向?qū)ο蟮恼Z(yǔ)言一樣概念的繼承,js里邊所說(shuō)的繼承是指模擬繼承。
具體js繼承是干啥呢,剛開(kāi)始做前端的時(shí)候我是用來(lái)面試的(最早寫(xiě)些小效果的時(shí)候基本用不到,為啥要看呢,因?yàn)槊嬖嚬俸軔?ài)問(wèn)這個(gè)問(wèn)題啊),所以就看看大概的,面試時(shí)候能說(shuō)個(gè)大概,在這個(gè)問(wèn)題上算是面試黨了。后來(lái)跟著慢慢的實(shí)際上雖然概念不是很明確也用到一些。
真正是用來(lái)干啥的呢,主要是用來(lái)復(fù)用我們之前寫(xiě)過(guò)的代碼。比如寫(xiě)過(guò)一個(gè)功能,一個(gè)對(duì)象,或者用別人寫(xiě)的東西,我們要自己加點(diǎn)兒什么,總不能改人家的東西吧,直接繼承過(guò)來(lái)用一下就好了,這才是繼承的真正用途。
js繼承怎么實(shí)現(xiàn):
先不上代碼,先說(shuō)說(shuō)想法。其實(shí)繼承呢就是想辦法把其他對(duì)象(js里邊一切皆對(duì)象哈)的屬性或者方法搞到我們自己的對(duì)象上,讓我們自己的這個(gè)對(duì)象可以用。這也就達(dá)到復(fù)用的目的了。
目的搞明白了,下面就是實(shí)現(xiàn)手段了。
根據(jù)js的特性,實(shí)現(xiàn)無(wú)非就是以下幾種方法的其中一種或者組合使用。
1、構(gòu)造函數(shù),js好像沒(méi)有嚴(yán)格的構(gòu)造函數(shù)的定義,但是可以用new來(lái)創(chuàng)建新的對(duì)象。構(gòu)造函數(shù)據(jù)說(shuō)也是嚴(yán)格的面向?qū)ο蟮恼Z(yǔ)言實(shí)現(xiàn)繼承的方法,那么js當(dāng)然可以模擬一下了,所以學(xué)過(guò)oop語(yǔ)言的人們會(huì)最先想到這個(gè)。
2、利用函數(shù)原型,利用原型鏈把兩個(gè)對(duì)象鏈接起來(lái),因?yàn)閖s原型鏈?zhǔn)潜容^獨(dú)特所以想到這個(gè)也是很容易的。
原型也分幾種,就是把什么作為繼承對(duì)象的原型,被繼承對(duì)象的原型或者被繼承對(duì)象的實(shí)例,或者直接被繼承者。這幾種作為繼承對(duì)象的原型得到的繼承效果是不一樣的。
3、復(fù)制屬性和方法,把被繼承對(duì)象的屬性或者方法統(tǒng)統(tǒng)復(fù)制克隆過(guò)來(lái)變成我們自己對(duì)象的屬性和方法就好了啊,我們就可以無(wú)比順暢的用了。當(dāng)然這個(gè)還分淺復(fù)制和深度復(fù)制兩種情況。
4、利用call和apply這兩個(gè)方法,這兩個(gè)方法比較神奇,可以改變函數(shù)執(zhí)行的上下文(this),所以利用這兩個(gè)方法也可以實(shí)現(xiàn)對(duì)被繼承對(duì)象的方法的繼承復(fù)用。
總的來(lái)js實(shí)現(xiàn)繼承的途徑大概就是這些,千變?nèi)f化的實(shí)現(xiàn)方法都是從這幾種方法的基礎(chǔ)上組合升級(jí)完善出來(lái)的,為毛大多數(shù)要組合使用呢,當(dāng)然是因?yàn)槭褂脝蝹€(gè)方法實(shí)現(xiàn)的效果不太理想啊。當(dāng)然可以根據(jù)自己項(xiàng)目中實(shí)際的需求選擇使用哪種方式,只要滿足自己的需求并沒(méi)有說(shuō)必須使用哪種方法去實(shí)現(xiàn)。就像說(shuō)從北京去石家莊,最快當(dāng)然是飛機(jī)啦。但是如果離機(jī)場(chǎng)遠(yuǎn),算上到機(jī)場(chǎng),從機(jī)場(chǎng)去市里,整體算下來(lái)還不如高鐵快,那就可以做高鐵。又比如自己有車可以開(kāi)車,想要挑戰(zhàn)一下還可以騎自行車,這個(gè)根據(jù)自己的實(shí)際情況來(lái)選就可以。
代碼實(shí)現(xiàn),下面結(jié)合代碼說(shuō)說(shuō)上面的幾種實(shí)現(xiàn)方法,有些是從其他地方摘來(lái)的,加點(diǎn)兒注釋啥的。
看了不少js繼承的東西也該總結(jié)總結(jié)了。
先說(shuō)一下大概的理解,有不對(duì)的還望指正,也好更正一下三觀。另外說(shuō)明下,下面的例子并非原創(chuàng)基本就是改了個(gè)變量名啥的,有的甚至直接拿過(guò)來(lái)用的。
js繼承是用來(lái)干啥的:
首先說(shuō)js沒(méi)有真正的跟其他面向?qū)ο蟮恼Z(yǔ)言一樣概念的繼承,js里邊所說(shuō)的繼承是指模擬繼承。
具體js繼承是干啥呢,剛開(kāi)始做前端的時(shí)候我是用來(lái)面試的(最早寫(xiě)些小效果的時(shí)候基本用不到,為啥要看呢,因?yàn)槊嬖嚬俸軔?ài)問(wèn)這個(gè)問(wèn)題啊),所以就看看大概的,面試時(shí)候能說(shuō)個(gè)大概,在這個(gè)問(wèn)題上算是面試黨了。后來(lái)跟著慢慢的實(shí)際上雖然概念不是很明確也用到一些。
真正是用來(lái)干啥的呢,主要是用來(lái)復(fù)用我們之前寫(xiě)過(guò)的代碼。比如寫(xiě)過(guò)一個(gè)功能,一個(gè)對(duì)象,或者用別人寫(xiě)的東西,我們要自己加點(diǎn)兒什么,總不能改人家的東西吧,直接繼承過(guò)來(lái)用一下就好了,這才是繼承的真正用途。
js繼承怎么實(shí)現(xiàn):
先不上代碼,先說(shuō)說(shuō)想法。其實(shí)繼承呢就是想辦法把其他對(duì)象(js里邊一切皆對(duì)象哈)的屬性或者方法搞到我們自己的對(duì)象上,讓我們自己的這個(gè)對(duì)象可以用。這也就達(dá)到復(fù)用的目的了。
目的搞明白了,下面就是實(shí)現(xiàn)手段了。
根據(jù)js的特性,實(shí)現(xiàn)無(wú)非就是以下幾種方法的其中一種或者組合使用。
1、構(gòu)造函數(shù),js好像沒(méi)有嚴(yán)格的構(gòu)造函數(shù)的定義,但是可以用new來(lái)創(chuàng)建新的對(duì)象。構(gòu)造函數(shù)據(jù)說(shuō)也是嚴(yán)格的面向?qū)ο蟮恼Z(yǔ)言實(shí)現(xiàn)繼承的方法,那么js當(dāng)然可以模擬一下了,所以學(xué)過(guò)oop語(yǔ)言的人們會(huì)最先想到這個(gè)。
2、利用函數(shù)原型,利用原型鏈把兩個(gè)對(duì)象鏈接起來(lái),因?yàn)閖s原型鏈?zhǔn)潜容^獨(dú)特所以想到這個(gè)也是很容易的。
原型也分幾種,就是把什么作為繼承對(duì)象的原型,被繼承對(duì)象的原型或者被繼承對(duì)象的實(shí)例,或者直接被繼承者。這幾種作為繼承對(duì)象的原型得到的繼承效果是不一樣的。
3、復(fù)制屬性和方法,把被繼承對(duì)象的屬性或者方法統(tǒng)統(tǒng)復(fù)制克隆過(guò)來(lái)變成我們自己對(duì)象的屬性和方法就好了啊,我們就可以無(wú)比順暢的用了。當(dāng)然這個(gè)還分淺復(fù)制和深度復(fù)制兩種情況。
4、利用call和apply這兩個(gè)方法,這兩個(gè)方法比較神奇,可以改變函數(shù)執(zhí)行的上下文(this),所以利用這兩個(gè)方法也可以實(shí)現(xiàn)對(duì)被繼承對(duì)象的方法的繼承復(fù)用。
總的來(lái)js實(shí)現(xiàn)繼承的途徑大概就是這些,千變?nèi)f化的實(shí)現(xiàn)方法都是從這幾種方法的基礎(chǔ)上組合升級(jí)完善出來(lái)的,為毛大多數(shù)要組合使用呢,當(dāng)然是因?yàn)槭褂脝蝹€(gè)方法實(shí)現(xiàn)的效果不太理想啊。當(dāng)然可以根據(jù)自己項(xiàng)目中實(shí)際的需求選擇使用哪種方式,只要滿足自己的需求并沒(méi)有說(shuō)必須使用哪種方法去實(shí)現(xiàn)。就像說(shuō)從北京去石家莊,最快當(dāng)然是飛機(jī)啦。但是如果離機(jī)場(chǎng)遠(yuǎn),算上到機(jī)場(chǎng),從機(jī)場(chǎng)去市里,整體算下來(lái)還不如高鐵快,那就可以做高鐵。又比如自己有車可以開(kāi)車,想要挑戰(zhàn)一下還可以騎自行車,這個(gè)根據(jù)自己的實(shí)際情況來(lái)選就可以。
代碼實(shí)現(xiàn),下面結(jié)合代碼說(shuō)說(shuō)上面的幾種實(shí)現(xiàn)方法,有些是從其他地方摘來(lái)的,加點(diǎn)兒注釋啥的。
一、構(gòu)造函數(shù)實(shí)現(xiàn)(借用構(gòu)造函數(shù)):
function Super(arg){
this.arr1 = "I'm super "+arg;
this.show = function(){
alert(this.arr1);
}
}
Super.prototype.say = function(){
alert(this.arr1);
}
function suber(arg){
Super.apply(this, arguments); //在suber的上下文中運(yùn)行super
}
var sub =new suber("suber");
var sub2 = new suber("suber1");
console.log(sub.arr1); //I'm super suber
console.log(sub.show); //function (){ alert(this.arr1);}
console.log(sub.say); //undefined
console.log(sub.show === sub2.show); //false
發(fā)現(xiàn)sub.say是undefined,這說(shuō)明它沒(méi)有被繼承過(guò)來(lái)啊,下邊兩個(gè)對(duì)象sub,sub2的show不相等,說(shuō)明兩個(gè)函數(shù)指向了兩個(gè)不同的對(duì)象,也就是說(shuō)被復(fù)制了兩份出來(lái)。
所以這個(gè)方法實(shí)現(xiàn)繼承的話原型對(duì)象上的屬性和方法沒(méi)有被繼承過(guò)來(lái),Super上的屬性和方法為每個(gè)new出來(lái)的對(duì)象分別復(fù)制一份。
所以單單使用這個(gè)方法來(lái)實(shí)現(xiàn)繼承還是不妥啊,因?yàn)樵蜕系姆椒ǘ紱](méi)有被繼承過(guò)來(lái)啊。于是大神們就想到了原型繼承
二、原型繼承:
function Super(arg){
this.arr1 = "I'm super "+arg;
this.show = function(){
alert(this.arr1);
}
}
Super.prototype.say = function(){
alert(this.arr1);
}
function suber(arg){}
suber.prototype = new Super();
var sub = new suber("suber1");
var sub2 = new suber("suber2");
console.log(sub.arr1); //I'm super undefined
console.log(sub.show); //function (){ alert(this.arr1);}
console.log(sub.say); //function (){ alert(this.arr1);}
console.log(sub.show === sub2.show); //true;
console.log(sub.say === sub2.say); //true;
這次是arr1繼承過(guò)來(lái)了,但是參數(shù)沒(méi)有添加進(jìn)來(lái),是undefined,所以這個(gè)方法子類聲明時(shí)候這個(gè)參數(shù)傳進(jìn)來(lái)付類繼承過(guò)來(lái)的這個(gè)屬性沒(méi)法收到。其他的都還算正常。show和say都繼承過(guò)來(lái)了。但是有一點(diǎn)兒需要注意,say是通過(guò)super的原型對(duì)象繼承過(guò)來(lái)的,而show是新建super對(duì)象實(shí)例時(shí)實(shí)例的屬性。
那么怎么實(shí)現(xiàn)參數(shù)傳輸又能把原型里邊的東東繼承過(guò)來(lái)呢,當(dāng)然上邊兩種方法組合一下就好了啊,于是前輩們又發(fā)明了下面這種方法
三、組合繼承(借用構(gòu)造函數(shù)并設(shè)置原型):
function Super(arg){
this.arr1 = "I'm super "+arg;
this.show = function(){
alert(this.arr1);
}
}
Super.prototype.say = function(){
alert(this.arr1);
}
function suber(arg){
Super.apply(this, arguments);
}
suber.prototype = new Super();
var sub = new suber("suber1");
var sub2 = new suber("suber2");
console.log(sub.arr1); //I'm super suber1
console.log(sub.show); //function (){ alert(this.arr1);}
console.log(sub.say); //function (){ alert(this.arr1);}
console.log(sub.show === sub2.show); //false;
console.log(sub.say === sub2.say); //true;
這次幾乎完美了,但是可以發(fā)現(xiàn)sub.show 和sub2.show并不相等啊,這是為啥呢,因?yàn)閍pply這個(gè)地方使得show成為了suber的自己的屬性,那么就吧suber原型里的show(Super的當(dāng)做suber原型對(duì)象的實(shí)例對(duì)象的show)給覆蓋了,所以又變成每次復(fù)制一個(gè),當(dāng)然這個(gè)地方?jīng)]有辦法避免啊。為了不產(chǎn)生這種多余的開(kāi)消這種可以共用的函數(shù)可以多放到原型對(duì)象里邊。
因?yàn)閟uber的構(gòu)造里邊的調(diào)用,和給suber原型對(duì)象賦值時(shí)候的調(diào)用導(dǎo)致Super被調(diào)用了兩次,那么每次new suber對(duì)象時(shí)候就調(diào)用了兩次Super,調(diào)用兩次就會(huì)產(chǎn)生兩個(gè)實(shí)例對(duì)象,需要消耗多余的資源了。
于是前輩們?yōu)榱私鉀Q這個(gè)問(wèn)題又開(kāi)了開(kāi)腦洞,開(kāi)發(fā)出來(lái)下面這種方法。
四、寄生組合繼承:
該方法跟方法三最主要的不同就是把父類原型賦給了子類原型而不是父類示例,看例子
function Super(arg){
this.arr1 = "I'm super "+arg;
}
Super.prototype.show = function(){ //這個(gè)方法放到了原型對(duì)象上。
alert(this.arr1);
}
Super.prototype.say = function(){
alert(this.arr1);
}
function suber(arg){
Super.apply(this, arguments);
}
/*inherit函數(shù)的作用,使用一個(gè)新的空函數(shù),來(lái)切斷父類對(duì)象的原型對(duì)象與子類原型對(duì)象的直接聯(lián)系,而是通過(guò)這個(gè)空構(gòu)造的實(shí)例對(duì)象實(shí)現(xiàn)繼承,這樣可以避免更改子類原型的屬性或者方法而影響了父類原型對(duì)象的屬性或者方法。*/
function inherit(obj){
function F(){}
F.prototype = obj;
return new F();
}
suber.prototype = inherit(Super.prototype);
var sub = new suber("suber1");
var sub2 = new suber("suber2");
console.log(sub.arr1); //I'm super suber1
console.log(sub.show); //function (){ alert(this.arr1);}
console.log(sub.say); //function (){ alert(this.arr1);}
console.log(sub.show === sub2.show); //true;
console.log(sub.say === sub2.say); //true;
好了,這樣就把三方法的弊端干掉了,這個(gè)可以完美的使用了吧。
五、復(fù)制屬性實(shí)現(xiàn)
拷貝我們可以寫(xiě)一個(gè)拷貝函數(shù)來(lái)實(shí)現(xiàn)。
function extend(Super,suber){
suber = suber || {};
for(var i in Super){
if(Super.hasOwnProperty(i)){
suber[i] = Super[i];
}
}
return suber;
}
var parent = {
name:"dad",
num:[1,2,3],
say:function(){alert("dad");}
}
var child = {
age:5,
sex:"boy"
};
child = extend(parent, child);
//以下測(cè)試
console.log(child); /*{
age:5,
sex:"boy",
name:"dad",
num:[1,2,3],
say:function(){alert("dad");}
}*/
console.log(child.say === parent.say); //true
console.log(child.num === parent.num); //true
復(fù)制成功,那么child成功繼承了parent的一些屬性,但是后面兩個(gè)測(cè)試發(fā)現(xiàn)他們是相等的,就表明了他們?cè)诠猛粋€(gè)數(shù)組,同一個(gè)函數(shù),函數(shù)這個(gè)可以,但是數(shù)組這個(gè)就有問(wèn)題了,如果一個(gè)chiild改變了數(shù)組,幾個(gè)被繼承對(duì)象的數(shù)組也跟著變了,這就不給力了啊。
為什么會(huì)發(fā)生這種情況呢,js里邊對(duì)象存儲(chǔ)的是指針,然后這個(gè)指針指向這個(gè)值,我們?cè)谶@復(fù)制的實(shí)際是指向該對(duì)象的指針的值,所以繼承對(duì)象和被繼承對(duì)象都指向了同一個(gè)對(duì)象,接下來(lái)看看如何使用深度復(fù)制來(lái)解決這個(gè)問(wèn)題。
深度復(fù)制對(duì)象屬性:
function extenddeep(Super, suber){
var tostr = Object.prototype.toString, astr = "[object Array]";
suber = suber || {};
for(var i in Super){
if(Super.hasOwnProperty(i)){
if(typeof Super[i] === "object"){
suber[i] = (tostr.call(Super[i]) == astr) ? [] : {};
extenddeep(Super[i],suber[i]);
}else {
suber[i] = Super[i];
}
}
}
return suber;
}
var parent = {
name:"papa",
num:[1,2,3],
say:function(){alert("I'm father of my son!");}
}
var child = {
name:"jone",
sex:"boy",
}
var kid = extenddeep(parent, child);
console.log(kid); // {name: "papa"
num: Array[3]
say: ()
sex: "boy"
// }
console.log(kid.say === parent.say); //true
console.log(kid.num === parent.num); //false
console.log(kid.name); //papa
好了,深度復(fù)制完畢,但似有木有發(fā)現(xiàn)問(wèn)題,name是parent的,也就是說(shuō)如果繼承對(duì)象有和被繼承對(duì)象一樣的屬性名的屬性如果不做處理就會(huì)被替換掉。那么我們可以做一下處理,先聲明一個(gè)屬性,保存parent里的東西,剩下的的當(dāng)然就是child自己的東西了,最后再把屬性給child對(duì)象就可以了。
六、利用call和apply這兩個(gè)方法(借用方法)。
這個(gè)就是通過(guò)call和apply來(lái)復(fù)用其他對(duì)象的方法,達(dá)到復(fù)用的目的。
var one = {
name:"object",
say: function(greet){
return greet + ', ' + this.name;
}
}
var tow = {
name:"two"
}
one.say.call(tow, "hi"); //hi, two
這個(gè)就是借用了,好了,下課。
好吧,好吧,其實(shí)這里邊還有其他東西要看。可以借用并不“帶表”可以隨便把某個(gè)方法賦值給誰(shuí)然后跟沒(méi)發(fā)生什么似的繼續(xù)用。所以我們平時(shí)使用借用時(shí)要注意一下上下文,下面看下那些容易出錯(cuò)的地方。
//賦值給一個(gè)變量時(shí)候上下文會(huì)變化
var say = one.say;
console.log(say('hoho')); // "hoho, undefined"
//作為回調(diào)函數(shù)時(shí)也會(huì)發(fā)生變化
var yetother = {
name:"yetother obj",
method:function(callback){
return callback("Hola");
}
}
console.log(yetother.method(one.say)); //"Hola, "
神馬意思呢,就是this.name是undefined,當(dāng)one.say賦值給say是,實(shí)際上是say存儲(chǔ)了指向函數(shù)對(duì)象的指針,say這個(gè)變量明顯又是全局變量的一個(gè)屬性,那么它運(yùn)行的時(shí)候?qū)嶋H的上下文就變成了windows了,當(dāng)然這個(gè)時(shí)候name就變成undefined了?;卣{(diào)這個(gè)也是一樣,return 的是函數(shù)運(yùn)行的結(jié)果。如果我們事先設(shè)置 windows.name="windows" 那么得到的結(jié)果就變成了 "hoho, windows" 和"Hola, windows" 了。
function bind(o, m){
return function(){
return m.apply(o, [].slice.call(arguments));
}
}
var othersay = bind(yetother, one.say);
othersay("Hola"); //"Hola, yetother obj"
通過(guò)apply可以改變方法執(zhí)行的上下文,那么我們構(gòu)建一個(gè)函數(shù)來(lái)實(shí)現(xiàn)這樣一個(gè)功能,通過(guò)使用方法調(diào)用實(shí)現(xiàn)上下文的改變,這樣就不會(huì)出現(xiàn)上下文不是我們期望的上下文的情況了。
//這段是直接復(fù)制過(guò)來(lái)的。
// ECMAScript 5給Function.prototype添加了一個(gè)bind()方法,以便很容易使用apply()和call()。
if (typeof Function.prototype.bind === 'undefined') {
Function.prototype.bind = function (thisArg) {
var fn = this,
slice = Array.prototype.slice,
args = slice.call(arguments, 1);
return function () {
return fn.apply(thisArg, args.concat(slice.call(arguments)));
};
};
}
var twosay2 = one.say.bind(two);
console.log(twosay2('Bonjour')); // "Bonjour, another object"
var twosay3 = one.say.bind(two, 'Enchanté');
console.log(twosay3()); // "Enchanté, another object"
介紹完了,該說(shuō)說(shuō)自己的疑惑了,當(dāng)復(fù)制屬性方法遇到的被繼承對(duì)象里邊存在方法,如何單獨(dú)復(fù)制出來(lái)呢,現(xiàn)在的是直接共用了,因?yàn)楫吘狗椒ㄒ话悴粫?huì)經(jīng)常改動(dòng)。求解答?
下面是轉(zhuǎn)載過(guò)來(lái)的jQuery的extend方法,好像也沒(méi)有特殊處理函數(shù)這塊,繼承完了兩個(gè)函數(shù)也是共用的。
$.extend源碼
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false ;
// Handle a deep copy situation
//如果第一個(gè)參數(shù)是boolean類型
//修正參數(shù),將第二個(gè)參數(shù)作為target
if ( typeof target === "boolean" ) {
deep = target;
// skip the boolean and the target
target = arguments[ i ] || {};
//i++是為了后續(xù) i === length的判斷
i++;
}
// Handle case when target is a string or something (possible in deep copy)
//如果目標(biāo)既不是對(duì)象也不是方法(例如給基本類型擴(kuò)展屬性方法和屬性不會(huì)報(bào)錯(cuò)但是是無(wú)用的),修正target為 js對(duì)象
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
//如果只有一個(gè)參數(shù),修正對(duì)象為JQuery函數(shù)或JQuery對(duì)象
if ( i === length ) {
target = this ;
//修正target所在位置,后面的都是要添加給target的對(duì)象
i--;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
//如果target和copy是同一個(gè)對(duì)象,略過(guò),防止自己的屬性引用了本身對(duì)象導(dǎo)致的循環(huán)引用,以致GC無(wú)法回收
if ( target === copy ) {
continue ;
}
// Recurse if we're merging plain objects or arrays
//如果是deep為true,并且要添加給target的copy為對(duì)象獲數(shù)組
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false ;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
//很巧妙 ,用一個(gè)遞歸,實(shí)現(xiàn)引用對(duì)象的深克隆,遞歸的返回條件是屬性石基本類型,基本類型都是深克隆
target[ name ] = jQuery.extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
//淺克隆
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
以上這篇javascript 繼承學(xué)習(xí)心得總結(jié)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考