js中對象的復(fù)制最筒,淺復(fù)制(淺拷貝)和深復(fù)制(深拷貝)

在js中,我們經(jīng)常復(fù)制一個對象蔚叨,復(fù)制數(shù)據(jù)床蜘,那么就會有人問了,怎么復(fù)制蔑水?

JS中對象分為基本類型和復(fù)合(引用)類型邢锯,基本類型存放在棧內(nèi)存,復(fù)合(引用)類型存放在堆內(nèi)存搀别。

堆內(nèi)存用于存放由new創(chuàng)建的對象丹擎,棧內(nèi)存存放一些基本類型的變量和對象的引用變量。

至于堆內(nèi)存和棧內(nèi)存的區(qū)別介紹领曼,你們可以百度看看。

下面開始講解復(fù)制:

這種只是簡單的變量蛮穿,內(nèi)存小庶骄,我們直接復(fù)制不會發(fā)生引用。

var a=123;
var b=a;
a=123456;
alert(a); //123456
alert(b); //123

//或者是

var a='afafas';
var b=a;
a='fgfdsdsgs';
alert(a); //fgfdsdsgs
alert(b); //afafas

而對于對象這種內(nèi)存占用比較大的來說践磅,直接讓復(fù)制的東西等于要復(fù)制的单刁,那么就會發(fā)生引用,因為這種復(fù)制,只是將復(fù)制出來的東西的指向指向了要復(fù)制的那個東西羔飞,簡單的說肺樟,就是兩個都同時指向了一個空間,如果改變其中一個逻淌,另一個也會發(fā)生變化么伯。這就發(fā)生了引用。

引用只發(fā)生在對象的身上:

var arr1=[1,2,3];
var arr2=arr1;
arr1.push(4);
alert(arr1); //1234
alert(arr2); //1234
arr2.push(5);
alert(arr1); //12345
alert(arr2); //12345

那么對于數(shù)組卡儒,ES6我們復(fù)制有新的兩種方法田柔,不會發(fā)生引用。

第一種:Array.from(要復(fù)制的數(shù)組);

var arr1=[1,2,3];
var arr2=Array.from(arr1);
arr1.push(4);
alert(arr1);  //1234
alert(arr2);  //123
arr2.push(5);
alert(arr1);  //1234
alert(arr2);  //1235

第二種:...

var arr1=[1,2,3];
var arr2=[...arr1];
arr1.push(4);
alert(arr1);  //1234
alert(arr2);  //123
arr2.push(5);
alert(arr1);  //1234
alert(arr2);  //1235

第二種這個方法也可以用在函數(shù)的行參上面骨望。

function show(...arr1){  //直接來復(fù)制arguments這個偽數(shù)組硬爆,讓它變成真正的數(shù)組,從而擁有數(shù)組的方法擎鸠。
  alert(arr1); //1234
  arr1.push(5);
  alert(arr1); //12345
}
show(1,2,3,4)

或者是通過循環(huán)來復(fù)制:

var arr1=[1,2,3,4];
var arr2=[];
for(var i=0; i<arr1.length; i++){
  arr2[i]=arr1[i];
}
arr1.push(5);
arr2.push(6);
alert(arr1); //12345
alert(arr2); //12346

//或者是json

var json1={"name":"鵬哥","age":24,"job":"前端開發(fā)"};
var json2={};
for(var name in json1){
  json2[name]=json1[name];
}
alert(JSON.stringify(json1)); //{"name":"鵬哥","age":24,"job":"前端開發(fā)"}
alert(JSON.stringify(json2)); //{"name":"鵬哥","age":24,"job":"前端開發(fā)"}
json1.a=1;
json2.b=2;
alert(JSON.stringify(json1)); //{"name":"鵬哥","age":24,"job":"前端開發(fā)","a":1}
alert(JSON.stringify(json2)); //{"name":"鵬哥","age":24,"job":"前端開發(fā)","b":2}

深復(fù)制和淺復(fù)制最根本的區(qū)別在于是否是真正獲取了一個對象的復(fù)制實體缀磕,而不是引用,

1)深復(fù)制在計算機中開辟了一塊內(nèi)存地址用于存放復(fù)制的對象劣光,
  2)而淺復(fù)制僅僅是指向被復(fù)制的內(nèi)存地址袜蚕,如果原地址中對象被改變了,那么淺復(fù)制出來的對象也會相應(yīng)改變赎线。

所謂的淺復(fù)制廷没,只是拷貝了基本類型的數(shù)據(jù),而引用類型數(shù)據(jù)垂寥,復(fù)制后也是會發(fā)生引用颠黎,我們把這種拷貝叫做“(淺復(fù)制)淺拷貝”。

看例子:

var json1 = {"a":"李鵬","arr1":[1,2,3]}
function copy(obj1) {
    var obj2 = {};
    for (var i in obj1) {
      obj2[i] = obj1[i];
    }
    return obj2;
}
var json2 = copy(json1);
json1.arr1.push(4);
alert(json1.arr1);  //1234
alert(json2.arr1)  //1234

而深復(fù)制的話滞项,我們要求復(fù)制一個復(fù)雜的對象狭归,那么我們就可以利用遞歸的思想來做,及省性能文判,又不會發(fā)生引用过椎。

看例子:

var json1={"name":"鵬哥","age":18,"arr1":[1,2,3,4,5],"string":'afasfsafa',"arr2":[1,2,3,4,5],"arr3":[{"name1":"李鵬"},{"job":"前端開發(fā)"}]};
var json2={};
function copy(obj1,obj2){
  var obj2=obj2||{}; //最初的時候給它一個初始值=它自己或者是一個json
  for(var name in obj1){
    if(typeof obj1[name] === "object"){ //先判斷一下obj[name]是不是一個對象
      obj2[name]= (obj1[name].constructor===Array)?[]:{}; //我們讓要復(fù)制的對象的name項=數(shù)組或者是json
      copy(obj1[name],obj2[name]); //然后來無限調(diào)用函數(shù)自己 遞歸思想
    }else{
      obj2[name]=obj1[name];  //如果不是對象,直接等于即可戏仓,不會發(fā)生引用疚宇。
    }
  }
  return obj2; //然后在把復(fù)制好的對象給return出去
}
json2=copy(json1,json2)
json1.arr1.push(6);
alert(json1.arr1);  //123456
alert(json2.arr1);  //12345

以上,結(jié)束赏殃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敷待,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子仁热,更是在濱河造成了極大的恐慌榜揖,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異举哟,居然都是意外死亡思劳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門妨猩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來潜叛,“玉大人,你說我怎么就攤上這事册赛∧频迹” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵森瘪,是天一觀的道長牡属。 經(jīng)常有香客問我,道長扼睬,這世上最難降的妖魔是什么逮栅? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮窗宇,結(jié)果婚禮上措伐,老公的妹妹穿的比我還像新娘。我一直安慰自己军俊,他們只是感情好侥加,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粪躬,像睡著了一般担败。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镰官,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天提前,我揣著相機與錄音,去河邊找鬼泳唠。 笑死狈网,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的笨腥。 我是一名探鬼主播拓哺,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脖母!你這毒婦竟也來了士鸥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤镶奉,失蹤者是張志新(化名)和其女友劉穎础淤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哨苛,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡鸽凶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了建峭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玻侥。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖亿蒸,靈堂內(nèi)的尸體忽然破棺而出凑兰,到底是詐尸還是另有隱情,我是刑警寧澤边锁,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布姑食,位于F島的核電站,受9級特大地震影響茅坛,放射性物質(zhì)發(fā)生泄漏音半。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一贡蓖、第九天 我趴在偏房一處隱蔽的房頂上張望曹鸠。 院中可真熱鬧,春花似錦斥铺、人聲如沸彻桃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽邻眷。三九已至,卻和暖如春笙纤,著一層夾襖步出監(jiān)牢的瞬間耗溜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工省容, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抖拴,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓腥椒,卻偏偏與公主長得像阿宅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子笼蛛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Java8張圖 11洒放、字符串不變性 12、equals()方法滨砍、hashCode()方法的區(qū)別 13往湿、...
    Miley_MOJIE閱讀 3,693評論 0 11
  • __block和__weak修飾符的區(qū)別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用妖异,...
    LZM輪回閱讀 3,284評論 0 6
  • 1.寫一個NSString類的實現(xiàn) +(id)initWithCString:(c*****t char *)nu...
    韓七夏閱讀 3,747評論 2 37
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理领追。運行時機制的原理和運用場景他膳。SDWebImage的原...
    LZM輪回閱讀 2,004評論 0 12
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,125評論 29 470