這篇文章給大家介紹JS中實(shí)現(xiàn)淺拷貝和深拷貝,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

岳西網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)2013年開(kāi)創(chuàng)至今到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
(一)JS中基本類型和引用類型
JavaScript的變量中包含兩種類型的值:基本類型值 和 引用類型值,在內(nèi)存中的表現(xiàn)形式在于:前者是存儲(chǔ)在棧中的一些簡(jiǎn)單的數(shù)據(jù)段,后者則是保存在堆內(nèi)存中的一個(gè)對(duì)象。
基本類型值
在JavaScript中基本數(shù)據(jù)類型有 String , Number , Undefined , Null , Boolean ,在ES6中,又定義了一種新的基本數(shù)據(jù)類型 Symbol ,所以一共有6種。
基本類型是按值訪問(wèn)的,從一個(gè)變量復(fù)制基本類型的值到另一個(gè)變量后,這兩個(gè)變量的值是完全獨(dú)立的,即使一個(gè)變量改變了也不會(huì)影響到第二個(gè)變量。
var str1 = '撩課'; var str2 = str1; str2 = 'itlike'; console.log(str2); //'itlike' console.log(str1); //'撩課'
引用類型值
引用類型值是引用類型的實(shí)例,它是保存在堆內(nèi)存中的一個(gè)對(duì)象,引用類型是一種數(shù)據(jù)結(jié)構(gòu),最常用的是Object,Array,Function類型,此外還有Date,RegExp,Error等。
在ES6中提供了Set,Map2種新的數(shù)據(jù)結(jié)構(gòu)。
(二)JS中如何復(fù)制引用類型的
基本類型和引用類型賦值的差異化
舉個(gè)例子:在下面代碼中,只修改了obj1中的name屬性,卻同時(shí)改變了ob1和obj2中的name屬性。
var obj1 = {'name': '撩課'};
var obj2 = obj1;
obj2.name = '小撩';
console.log(obj1); // {'name': '撩課'}
console.log(obj2); // {'name': '撩課'}當(dāng)變量復(fù)制引用類型值的時(shí)候,同樣和基本類型值一樣會(huì)將變量的值復(fù)制到新變量上,不同的是對(duì)于變量的值,它是一個(gè)指針,指向存儲(chǔ)在堆內(nèi)存中的對(duì)象。
因?yàn)椋贘S中,堆內(nèi)存中的對(duì)象無(wú)法直接訪問(wèn),必須要訪問(wèn)這個(gè)對(duì)象在堆內(nèi)存中的地址,然后再按照這個(gè)地址去獲得這個(gè)對(duì)象中的值。
(三)淺拷貝
在JS中,如果屬性是基本類型,拷貝的就是基本類型的值;如果屬性是引用類型,拷貝的就是內(nèi)存地址;所以如果其中一個(gè)對(duì)象改變了這個(gè)地址,就會(huì)影響到另一個(gè)對(duì)象。
下面是JavaScript提供的淺拷貝方法:
Object.assign
ES6中拷貝對(duì)象的方法,接受的第一個(gè)參數(shù)是拷貝的目標(biāo),剩下的參數(shù)是拷貝的源對(duì)象;
語(yǔ)法:Object.assign(target, ...sources)
var p = {
'name': '張三',
};
var copyP = {};
Object.assign(copyP, p);
console.log(copyP);
console.log(p);Object.assign是一個(gè)淺拷貝,它只是在根屬性(對(duì)象的第一層級(jí))創(chuàng)建了一個(gè)新的對(duì)象,但是如果屬性的值是對(duì)象的話,只會(huì)拷貝一份相同的內(nèi)存地址。
擴(kuò)展運(yùn)算符
利用擴(kuò)展運(yùn)算符可以在構(gòu)造字面量對(duì)象時(shí),進(jìn)行克隆或者屬性拷貝。語(yǔ)法如下:
var cloneObj = { ...obj };
var obj = {'name': '撩課', 'college': ['H5','JAVA','Python']}
var obj2 = {...obj};
obj.name='小撩';
//{'name': '小撩', 'college': ['H5','JAVA','Python']}
console.log(obj);
//{'name': '撩課', 'college': ['H5','JAVA','Python']}
console.log(obj2);
obj.college.push('Go');
//{'name': '小撩', 'college': ['H5','JAVA','Python','Go']}
console.log(obj);
//{'name': '小撩', 'college': ['H5','JAVA','Python','Go']}
console.log(obj2);擴(kuò)展運(yùn)算符和Object.assign()存在同樣的問(wèn)題,對(duì)于值是對(duì)象的屬性無(wú)法完全拷貝成兩個(gè)不同對(duì)象;
但是如果屬性都是基本類型的值的話,使用擴(kuò)展運(yùn)算符更加簡(jiǎn)潔。
(四)深拷貝
淺拷貝只在根屬性上在堆內(nèi)存中創(chuàng)建了一個(gè)新的的對(duì)象,復(fù)制了基本類型的值,但是復(fù)雜數(shù)據(jù)類型也就是對(duì)象則是拷貝相同的地址。
而深拷貝則是將一個(gè)對(duì)象從內(nèi)存中完整的拷貝一份出來(lái),從堆內(nèi)存中開(kāi)辟一個(gè)新的區(qū)域存放新對(duì)象,且修改新對(duì)象不會(huì)影響原對(duì)象。
JSON.stringify
JSON.stringify()是目前開(kāi)發(fā)過(guò)程中最常用的深拷貝方式,原理是把一個(gè)對(duì)象序列化成為一個(gè)JSON字符串,將對(duì)象的內(nèi)容轉(zhuǎn)換成字符串的形式再保存在內(nèi)存中,再用JSON.parse()反序列化將JSON字符串變成一個(gè)新的對(duì)象。
舉個(gè)例子:
var obj = {
name: '撩課',
age: 18,
friends: ['小花', '小黑'],
goodF: {
name: '小撩',
age: 19,
address: '上海',
pets: [{name: '土豆'}, {name: '馬鈴薯'}]},
bir: new Date()
};
var newObj = JSON.parse(JSON.stringify(obj));
obj.goodF.pets[0].name = '旺財(cái)';
console.log(newObj);
console.log(obj);使用JSON.stringify實(shí)現(xiàn)深拷貝有幾點(diǎn)要注意:
1)拷貝的對(duì)象的值中如果有函數(shù),undefined,symbol,經(jīng)過(guò)JSON.stringify()序列化后的JSON字符串中這個(gè)鍵值對(duì)會(huì)消失;
無(wú)法拷貝不可枚舉的屬性,無(wú)法拷貝對(duì)象的原型鏈
3)拷貝Date引用類型會(huì)變成字符串
4)拷貝RegExp引用類型會(huì)變成空對(duì)象
對(duì)象中含有NaN、Infinity和-Infinity,則序列化的結(jié)果會(huì)變成null
遞歸實(shí)現(xiàn)深拷貝
具體實(shí)現(xiàn)如下:
/**
* 輔助函數(shù), 判定是否是對(duì)象
* @param obj
* @returns {boolean}
*/
function isObj(obj) {
return obj instanceof Object;
}
/**
* 深拷貝fromObj面的所有屬性/值, 到toObj對(duì)象里面
* @param fromObj 拷貝對(duì)象
* @param toObj 目標(biāo)對(duì)象
*/
function deepCopyObj2NewObj(fromObj, toObj) {
for (var key in fromObj) {
if(fromObj.hasOwnProperty(key)){
var fromValue = fromObj[key];
// 如果是值類型,那么就直接拷貝賦值
if (!isObj(fromValue)) {
toObj[key] = fromValue;
} else {
// 如果是引用類型,那么就再調(diào)用一次這個(gè)方法,
// 去內(nèi)部拷貝這個(gè)對(duì)象的所有屬性
// fromValue是什么類型, 創(chuàng)建一個(gè)該類型的空對(duì)象
var tmpObj = new fromValue.constructor;
// console.log(tmpObj);
// debugger;
deepCopyObj2NewObj(fromValue, tmpObj);
toObj[key] = tmpObj;
}
}
}
}關(guān)于JS中實(shí)現(xiàn)淺拷貝和深拷貝就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
本文題目:JS中實(shí)現(xiàn)淺拷貝和深拷貝
鏈接地址:http://chinadenli.net/article40/goeoho.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、標(biāo)簽優(yōu)化、、品牌網(wǎng)站建設(shè)、微信公眾號(hào)、網(wǎng)站設(shè)計(jì)公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)