目录
一、浅拷贝
1.概念:
2.实现方法
2.1 Object.assign(target,…source)
2.2 Array.prototype.slice()
2.3 Array.prototype.concat()
二、深拷贝
1. 概念
2. 实现方法
2.1 _.cloneDeep()
2.2 Json.parse(Json.stringify(obj))
2.3 JQuery中&.extend(deep,{},obj)
2.4 循环递归
一、浅拷贝
1.概念:
如果属性是基本类型,则为值传递,如果属性是引用类型则拷贝内存地址,即共用内存地址,改变任意一个则另一个内存地址指向也变化。
2.实现方法
- Object.assign(target,…source)
- Array.prototype.slice()
- Array.prototype.concat()
2.1 Object.assign(target,…source)
var obj1 = { name : 'ggg', age : 18, sex : '女', stu : { name :'mmm' } } var obj2 = Object.assign({},obj1) console.log(obj2) obj1.name = 'hhh'; obj2.stu.name = 'kkk'; console.log(obj1); console.log(obj2);
复制
控制台输出为:
1)、Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象,继承属性和不可枚举属性是不能拷贝的。
2)、针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。
3)、目标对象自身也会改变
4)、异常会打断后续拷贝任务
5)、目前IE浏览器不兼容Object.assign(),如果需要兼容IE的话最好不要直接使用这个方法。
2.2 Array.prototype.slice()
var arr = ['a','b','c']; var arr1 = arr.slice(0) console.log(arr1); arr1[1] = 'd'; console.log(arr1); console.log(arr);
复制
控制台输出结果为:
2.3 Array.prototype.concat()
var arr = ['a','b','c']; var arr1 = arr.concat() console.log(arr1); arr[2] = 'd'; console.log(arr1); console.log(arr);
复制
二、深拷贝
1. 概念
新开辟一个新的栈,所有元素或属性均完全赋值,与源对象完全脱离,对应两个不同的地址,新对象修改不会反映到源对象中。
2. 实现方法
2.1 _.cloneDeep()
const obj2 = _.cloneDeep(obj1);
复制
2.2 Json.parse(Json.stringify(obj))
const obj2 = JSON.parse(JSON.stringify(obj1));
复制
但是这种方式存在弊端,会忽略undefined
、symbol
和函数。
2.3 JQuery中&.extend(deep,{},obj)
使用之前先引入JQuery
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
复制
var obj1 = { name : undefined, name2 : 'ggg', age : 18, b : { f : { g : 2} }, c : [ 3,4,5 ], d : function() { sex = 'nv' }, s : Symbol('A') }; const obj2 = $.extend(true,{},obj1) console.log(obj2); obj1.age = 45; obj2.b.f.g = 7 console.log(obj1); console.log(obj2);
复制
控制台输出:
2.4 循环递归
// 递归调用 const deepCopy = (obj) => { // 判断传入的值是否为一个对象 if (obj === null && typeof obj !== "object") { return obj; } // 判断对象的类型 注意这里不考虑包装类对象 if (Object.prototype.toString.call(obj) === "[object Date]") { return new Date(obj); } if (Object.prototype.toString.call(obj) === "[object RegExp]") { return new RegExp(obj); } if (Object.prototype.toString.call(obj) === "[object Undefined]") { return new Error(obj); } // 判断对象是类 let newObj = Array.isArray(obj) ? [] : {} for(let item in obj){ if(typeof obj[item] === 'object') { newObj[item] = deepCopy(obj[item]) }else { newObj[item] = obj[item] } } return newObj }; const obj2 = deepCopy(obj1) console.log(obj1); obj2.age = 25; console.log(obj1); console.log(obj2);
复制
控制台输出: