什么是js深拷貝與淺拷貝及其完成方式
發(fā)表時(shí)間:2023-12-25 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]今天來給大家說一下JS的js深拷貝和淺拷貝,它們有什么區(qū)別,有什么作用呢?下面給大家舉例說明一下。var m = { a: 10, b: 20 }var n = m;n.a = 15;// 這時(shí)m.a的值是多少m.a會(huì)輸出15,因?yàn)檫@是淺拷貝,n和m指向的是同一個(gè)堆,對(duì)象復(fù)制只是復(fù)制的對(duì)象的引用。...
今天來給大家說一下JS的js深拷貝和淺拷貝,它們有什么區(qū)別,有什么作用呢?下面給大家舉例說明一下。
var m = { a: 10, b: 20 }var n = m;n.a = 15;// 這時(shí)m.a的值是多少
m.a會(huì)輸出15,因?yàn)檫@是淺拷貝,n和m指向的是同一個(gè)堆,對(duì)象復(fù)制只是復(fù)制的對(duì)象的引用。
深拷貝
深拷貝和上面淺拷貝不同,就是徹底copy一個(gè)對(duì)象,而不是copy對(duì)象的引用,例如,還是之前的例子,我們這么寫:
var m = { a: 10, b: 20 }var n = {a:m.a,b:m.b};n.a = 15;
這次,我們?cè)賮磔敵鰉.a ,發(fā)現(xiàn)m.a的值還是10,并沒有改變,m對(duì)象和n對(duì)象是雖然所有的值都是一樣的,但是在堆里面,對(duì)應(yīng)的不是同一個(gè)了,這個(gè)就是深拷貝。
深拷貝和淺拷貝
深拷貝和淺拷貝的示意圖大致如下:
淺拷貝只復(fù)制指向某個(gè)對(duì)象的指針,而不復(fù)制對(duì)象本身,新舊對(duì)象還是共享同一塊內(nèi)存。但深拷貝會(huì)另外創(chuàng)造一個(gè)一模一樣的對(duì)象,新對(duì)象跟原對(duì)象不共享內(nèi)存,修改新對(duì)象不會(huì)改到原對(duì)象。
淺拷貝的實(shí)現(xiàn)方式
1、可以通過簡(jiǎn)單的賦值實(shí)現(xiàn)
類似上面的例子,當(dāng)然,我們也可以封裝一個(gè)簡(jiǎn)單的函數(shù),如下:
function simpleClone(initalObj) {
var obj = {};
for ( var i in initalObj) {
obj[i] = initalObj[i];
}
return obj;
}
var obj = {
a: "hello",
b:{
a: "world",
b: 21
},
c:["Bob", "Tom", "Jenny"],
d:function() {
alert("hello world");
}
}
var cloneObj = simpleClone(obj);
console.log(cloneObj.b);
console.log(cloneObj.c);
console.log(cloneObj.d);
cloneObj.b.a = "changed";
cloneObj.c = [1, 2, 3];
cloneObj.d = function() { alert("changed"); };
console.log(obj.b);
console.log(obj.c);
console.log(obj.d);
2、Object.assign()實(shí)現(xiàn)
Object.assign() 方法可以把任意多個(gè)的源對(duì)象自身的可枚舉屬性拷貝給目標(biāo)對(duì)象,然后返回目標(biāo)對(duì)象。但是 Object.assign() 進(jìn)行的是淺拷貝,拷貝的是對(duì)象的屬性的引用,而不是對(duì)象本身。
var obj = { a: {a: "hello", b: 21} };var initalObj = Object.assign({}, obj);initalObj.a.a = "changed";console.log(obj.a.a); // "changed"
注意:當(dāng)object只有一層的時(shí)候,是深拷貝,例如如下:
var obj1 = { a: 10, b: 20, c: 30 };var obj2 = Object.assign({}, obj1);obj2.b = 100;console.log(obj1);// { a: 10, b: 20, c: 30 } <-- 沒被改到console.log(obj2);// { a: 10, b: 100, c: 30 }
深拷貝的實(shí)現(xiàn)方式
1、方法一還是手動(dòng)復(fù)制
和上面的舉例一樣,手動(dòng)復(fù)制可以實(shí)現(xiàn)深拷貝。
2、對(duì)象只有一層的話可以使用上面的:Object.assign()函數(shù)
3、轉(zhuǎn)成 JSON 再轉(zhuǎn)回來
var obj1 = { body: { a: 10 } };var obj2 = JSON.parse(JSON.stringify(obj1));obj2.body.a = 20;console.log(obj1);// { body: { a: 10 } } <-- 沒被改到console.log(obj2);// { body: { a: 20 } }console.log(obj1 === obj2);// falseconsole.log(obj1.body === obj2.body);// false
用JSON.stringify把對(duì)象轉(zhuǎn)成字符串,再用JSON.parse把字符串轉(zhuǎn)成新的對(duì)象。
可以封裝如下函數(shù)
var cloneObj = function(obj){
var str, newobj = obj.constructor === Array ? [] : {};
if(typeof obj !== 'object'){
return;
} else if(window.JSON){
str = JSON.stringify(obj), //系列化對(duì)象
newobj = JSON.parse(str); //還原
} else {
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ?
cloneObj(obj[i]) : obj[i];
}
}
return newobj;};
4、遞歸拷貝
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.constructor === Array) ? [] : {};
arguments.callee(prop, obj[i]);
} else {
obj[i] = prop;
}
}
return obj;}var str = {};var obj = { a: {a: "hello", b: 21} };deepClone(obj, str);console.log(str.a);
5、使用Object.create()方法
直接使用var newObj = Object.create(oldObj),可以達(dá)到深拷貝的效果。
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.constructor === Array) ? [] : Object.create(prop);
} else {
obj[i] = prop;
}
}
return obj;}
6、jquery
jquery 有提供一個(gè)$.extend可以用來做 Deep Copy。
var $ = require('jquery');var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]};var obj2 = $.extend(true, {}, obj1);console.log(obj1.b.f === obj2.b.f);// false
7、lodash
另外一個(gè)很熱門的函數(shù)庫lodash,也有提供_.cloneDeep用來做 Deep Copy。
var _ = require('lodash');var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]};var obj2 = _.cloneDeep(obj1);console.log(obj1.b.f === obj2.b.f);// false
這個(gè)性能還不錯(cuò),使用起來也很簡(jiǎn)單。
相信看了這些案例你已經(jīng)掌握了方法,更多精彩請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
相關(guān)閱讀:
HTML里的最后一行文字顯示不全怎么處理
怎樣用css3做出圖標(biāo)效果
CSS的編碼怎么轉(zhuǎn)換
以上就是什么是js深拷貝和淺拷貝及其實(shí)現(xiàn)方式的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
網(wǎng)站建設(shè)是一個(gè)廣義的術(shù)語,涵蓋了許多不同的技能和學(xué)科中所使用的生產(chǎn)和維護(hù)的網(wǎng)站。