目录
一、浅拷贝
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);
控制台输出: