簡介
注:淺拷貝和深拷貝都只針對于像Object缴允, Array這樣的復(fù)雜對象荚守。
淺拷貝:淺拷貝只是復(fù)制了內(nèi)存地址,如果原地址中的對象改變了练般,淺拷貝出來的對象也會相應(yīng)改變矗漾。
深拷貝:開辟了一塊新的內(nèi)存存放地址和地址指向的對象,原地址的任何對象改變了踢俄,深拷貝出來的對象不變缩功。
區(qū)別:淺拷貝只復(fù)制對象的第一層屬性并不包括對象里面的引用類型數(shù)據(jù)、深拷貝是對對象以及對象的所有子對象進行拷貝
淺拷貝
1.實現(xiàn)淺拷貝的方法
(1)for...in只循環(huán)第一層
在上面的代碼中都办,我們創(chuàng)建了一個 shallowCopy 函數(shù)嫡锌,它接收一個參數(shù)也就是被拷貝的對象。
- 首先創(chuàng)建了一個對象
- 然后 for...in 循環(huán)傳進去的對象琳钉,為了避免循環(huán)到原型上面會被遍歷到的屬性势木,使用 hasOwnProperty 限制循環(huán)只在對象自身,將被拷貝對象的每一個屬性和值添加到創(chuàng)建的對象當中
- 最后返回這個對象
這與直接賦值var obj3 = obj1的區(qū)別如下:
name | 和原數(shù)據(jù)是否指向同一對象 | 第一層數(shù)據(jù)為基本數(shù)據(jù)類型 | 原數(shù)據(jù)中包含子對象 |
---|---|---|---|
賦值 | 是 | 改變會使原數(shù)據(jù)一同改變 | 改變會使原數(shù)據(jù)一同改變 |
淺拷貝 | 否 | 改變不會使原數(shù)據(jù)一同改變 | 改變會使原數(shù)據(jù)一同改變 |
(2)ES6的Object.assign
Object.assign:用于對象的合并歌懒,將源對象(source)的所有可枚舉屬性啦桌,復(fù)制到目標對象(target),并返回合并后的target
用法: Object.assign(target, source1, source2); 所以 copyObj = Object.assign({}, obj); 這段代碼將會把obj中的一級屬性都拷貝到 {}中及皂,然后將其返回賦給copyObj
(3)ES6擴展運算符
擴展運算符(...)用于取出參數(shù)對象的所有可遍歷屬性甫男,拷貝到當前對象之中
(4)Array.prototype.slice()
(5)Array.prototype.concat()
.....
實現(xiàn)淺拷貝的方法還有很多,只需要記住淺拷貝的定義淺拷貝只是復(fù)制了內(nèi)存地址验烧,如果原地址中的對象改變了板驳,淺拷貝出來的對象也會相應(yīng)改變
深拷貝
(1)遞歸調(diào)用淺拷貝
對于深拷貝的對象,改變源對象不會對得到的對象有影響碍拆。只是在拷貝的過程中源對象的方法丟失了若治,這是因為在序列化 JavaScript 對象時,所有函數(shù)和原型成員會被有意忽略感混。
(2)JSON.stringify()和JSON.parse()
stringify 可以把一個 js 對象序列化為一個 JSON 字符串端幼,parse 可以把 JSON 字符串反序列化為一個 js 對象
但是這種方法也有不少壞處,譬如它會拋棄對象的constructor弧满。也就是深拷貝之后婆跑,不管這個對象原來的構(gòu)造函數(shù)是什么,在深拷貝之后都會變成Object庭呜。
這種方法能正確處理的對象只有可以轉(zhuǎn)成JSON格式的對象才可以這樣用( Number, String, Boolean, Array,...)