深浅拷贝
一、数据类型
在javaScript中数据类型分为两种基本数据类型和引用数据类型,它们的特点如下:
基本数据类型:存储在栈中,会创建一个完全相等的变量
引用数据类型:存储在堆中,存储的是地址。当被引用或者拷贝时,指向同一个地址
二、浅拷贝
1.浅拷贝的概念:
创建一个对象,该对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址,其中一个对象改变了这个地址,就会影响到另一个对象。:
2.浅拷贝常见的方法
2.1Object.assign()
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象分配到该目标对象。返回目标对象——MDN定义
语法:Obejct.assign(target, …sources),target表示目标对象,sources表示源对象
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
通过上面代码可以看出,如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的元对象属性。
除此之外,继承属性和不可枚举属性是不能拷贝的。
const obj = Object.create({foo: 1}, {
bar: {
value: 2 // bar是不可枚举属性
},
baz: {
value: 3,
enumerable: true // baz是个自身可枚举属性
}
})
const copy = Object.assign({}, obj)
console.log(copy) // {baz: 3}
2.2扩展运算符
利用扩展运算符,在构造对象是进行浅拷贝。语法:let cloneObj = {…obj}
/* 对象的拷贝 */
let obj = {a:1, b:{c:1}}
let obj2 = {...obj}
obj.a = 2
console.log(obj) //{a:2,b:{c:1}} console.log(obj2); //{a:1,b:{c:1}}
obj.b.c = 2
console.log(obj) //{a:2,b:{c:2}} console.log(obj2); //{a:1,b:{c:2}}
/* 数组的拷贝 */
let arr = [1, 2, 3];
let newArr = [...arr]; //跟arr.slice()是一样的效果
2.3数组中的concat和slice也可以实现浅拷贝
let arr = [1, 2, 3];
let newArr = arr.concat();
newArr[1] = 100;
console.log(arr); // [ 1, 2, 3 ]
console.log(newArr); // [ 1, 100, 3 ]
let arr = [1, 2, {val: 4}];
let newArr = arr.slice();
newArr[2].val = 1000;
console.log(arr); //[ 1, 2, { val: 1000 } ]
三,深拷贝
1深拷贝概念
将一个对象从内存中完整地拷贝出来一份给目标对象,并从堆内存中开辟一个全新的空间存放新对象,且新对象的修改并不会改变原对象,二者实现真正的分离。
2深拷贝方法
JSON.stringify():把一个对象序列化成为一个JSON字符串,并将对象里面的内容转换为字符串,最后再用JSON.parse()的方法将JSON字符串生成一个新的对象。
var obj1 = {
a:1,
b:[1,2,3]
}
var str = JSON.stringify(obj1)
var obj2 = JSON.parse(str)
console.log(obj2); //{a:1,b:[1,2,3]}
obj1.a=2
obj1.b.push(4);
console.log(obj1); //{a:2,b:[1,2,3,4]}
console.log(obj2); //{a:1,b:[1,2,3]}