深淺拷貝對(duì)于一個(gè)從前的我來說,太陌生了,于是乎,面試又是一場(chǎng)慘敗。其實(shí)還是很好理解的,深淺拷貝的原因,怎么寫深淺拷貝的方法,還是挺簡(jiǎn)單的。
Js的數(shù)據(jù)類型:
- 基本數(shù)據(jù)類型:null,undefined,數(shù)值類型,字符串類型,布爾類型
-
引用數(shù)據(jù)類型:對(duì)象類型(數(shù)組,日期,正則表達(dá)式,函數(shù))
基本類型保存在棧內(nèi)存中,引用類型值保存在堆內(nèi)存中,指針保存在棧內(nèi)存。這是因?yàn)闂?nèi)存只能存大小固定的數(shù)據(jù),而引用類型的值大小是不固定的。
- 基本類型的值復(fù)制,然后修改是互不影響的。
var a=10;
var b=a;
b=20;
a; // 10
- 引用類型的值復(fù)制的只是地址指針,而值是同一個(gè)堆內(nèi)存的數(shù)據(jù),所以修改屬性值時(shí)會(huì)互為影響,這就有了深淺拷貝的出現(xiàn)。
讓寫一個(gè)淺拷貝方法的時(shí)候,我總是認(rèn)為和基本類型值一樣復(fù)制也是一種,然而實(shí)際是不同的。
var a={x:10,y:20};
var b=a;
b === a;//true
var c = {...a};
c === a;//false
淺拷貝方法
用Es6的展開運(yùn)算符,可以簡(jiǎn)單快速的拷貝,如上一個(gè)demo。
for...in傳統(tǒng)方法,注意不要復(fù)制到原型上去。
var obj = {a:123,b:[1,2,3]};
function simpleClone(obj){
var temp={};
for(let i in obj){
if(obj.hasOwnProperty(i)){
temp.i = obj.i;
}
}
return temp;
}
simpleClone(obj);
//{i:undefined}
怎么錯(cuò)了呢,不是我想要的結(jié)果呢,哪里寫的不對(duì)嗎。原來還是基礎(chǔ)不牢固,for...in遍歷返回的是字符串類型,所以不能用obj.i,應(yīng)是obj[i]。
var obj = {a:123,b:[1,2,3]};
function simpleClone(obj){
var temp={};
for(let i in obj){
if(obj.hasOwnProperty(i)){
temp[i] = obj[i];
}
}
return temp;
}
simpleClone(obj);
//{a:123,b:[123]}
深拷貝方法
深拷貝簡(jiǎn)單粗暴的用遞歸,一層層的執(zhí)行下去。
function deepClone(initalObj, finalObj) {
var obj = finalObj || {};
for (var i in initalObj) {
var prop = initalObj[i];
// 避免相互引用對(duì)象導(dǎo)致死循環(huán),如initalObj.a = initalObj的情況
if(prop === obj) {
continue;
}
if (typeof prop === 'object') {
obj[i] = (prop instanceof Array) ? [] : {};
arguments.callee(prop, obj[i]);
} else {
obj[i] = prop;
}
}
return obj;
}
這是網(wǎng)上找的一段代碼,中間避免死循環(huán)的出現(xiàn),一直沒理解,相互引用怎么才能出現(xiàn)呢?