js 如何实现深拷贝

在浅拷贝中,对源或副本的更改可能也会导致其他对象的更改(因为两个对象共享相同的引用)。为了确保修改源或副本的时候不会导致其他对象发生更改,引入深拷贝。对象的深拷贝是指其属性与其拷贝的元对象属性不共享相同的引用(指向底层的值)。

浅拷贝

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存

浅拷贝的实现方式

展开语法、Array.prototype.concat()、Array.prototype.slice()、Array.from()、Object.assign() 和 Object.create();这些都是JavaScript实现浅拷贝的内置方法。

1、可以通过简单的赋值实现
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); // {a: 'world', b: 21}
console.log(cloneObj.c); // ['Bob', 'Tom', 'Jenny']
console.log(cloneObj.d); // ƒ () {  alert("hello world");  }

cloneObj.b.a = "changed"; 
cloneObj.c = [1, 2, 3]; 
cloneObj.d = function() { 
    alert("changed"); 
};

console.log(obj.b); // {a: 'changed', b: 21}
console.log(obj.c); // ['Bob', 'Tom', 'Jenny']
console.log(obj.d); // ƒ () {  alert("hello world"); }
2、Object.assign()实现

注意:当object只有一层的时候,是深拷贝,例如如下:

var obj = { a: {a: "hello", b: 21} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "changed";
console.log(obj.a.a); //  "changed"
3、展开运算符…

展开运算符是一个 es6 / es2015特性,它提供了一种非常方便的方式来执行浅拷贝,这与 Object.assign ()的功能相同。

let obj1 = { name: 'Kobe', address:{x:100,y:100}}
let obj2 = {...obj1}
obj1.address.x = 200;
obj1.name = 'wade'
console.log('obj2',obj2) // obj2 { name: 'Kobe', address: { x: 200, y: 100 } }
4、Array.prototype.concat()
let arr = [1, 3, {
    username: 'kobe'
    }];
let arr2 = arr.concat();    
arr2[2].username = 'wade';
console.log(arr); //[ 1, 3, { username: 'wade' } ]
5、Array.prototype.slice()
let arr = [1, 3, {
    username: ' kobe'
    }];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr); // [ 1, 3, { username: 'wade' } ]
6、函数库lodash的_.clone方法
var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.clone(obj1);
console.log(obj1.b.f === obj2.b.f);// true
深拷贝

深拷贝是指在拷贝一个对象时,不仅拷贝了对象本身,还拷贝了对象所引用的其他对象。相对于浅拷贝,深拷贝更加完整的复制了原对象,因此在一些需要保留原对象数据的场景中,深拷贝必不可少。

深拷贝的实现方式
1、如果JavaScript对象可以被序列化,可以使用 JSON.stringify() 将该对象转换为 JSON 字符串,然后使用 JSON.parse() 将该字符串转换回(全新的)JavaScript 对象
let ingredients_list = ["noodles", { list: ["eggs", "flour", "water"] }];

let ingredients_list_deepcopy = JSON.parse(JSON.stringify(ingredients_list));

ingredients_list_deepcopy[1].list = ["rice flour", "water"];

console.log(ingredients_list[1].list);  // Array(3) [ "eggs", "flour", "water" ]

上面那种方法在用的时候可以封装成下面函数

function deepCode(obj) {
	let newObj = obj.constructor === 'Array' ? [] : {};
	if (typeof obj !== 'object') return;
	if (window.JSON) {
		newObj = JSON.parse(JSON.stringify(obj)); // 先序列化对象再还原
	} else {
		for (i in obj) {
			newObj[i] = typeof obj[i] === 'object' ? deepCode(obj[i]) : obj[i];
		}
	}
	return newObj;
}
2、函数库lodash的_.cloneDeep方法
var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
3、递归拷贝

思路:遍历对象的所有属性,如果属性是基本类型,则直接拷贝,如果属性是引用类型,则递归拷贝该属性。

function deepCode(obj) {
	if (!obj) return obj;
	if (typeof obj.valueOf() == 'object') {
		const newObj = Array.isArray(obj) ? [] : {};
		for (let i in obj) {
			newObj[i] = typeof obj[i] === 'object' ? deepCode(obj[i]) : obj[i];
		}
		return newObj;
	} else {
		return obj.valueOf();
	}
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值