// 拷贝:
// ------简单数据类型拷贝: 不存在深浅拷贝。 值在栈中------------直接传值; 例:var a=10;---var b=a
// (1)浅拷贝:针对复杂(引用)数据类型,拷贝到栈中的值;
// ------(数组/对象)浅拷贝 地址在栈中------------传地址; 例:var obj1={id:123};---var obj2=obj1(obj1和obj2在栈中拷贝了得到了相同的地址,指向同一份堆中的数据)。
// (2) 深拷贝:针对复杂(引用)数据类型(数组/对象),拷贝堆中的值给新的数组/对象;------复杂数据类型拷贝堆中的值为深拷贝。
// 总结特点
// (1)浅拷贝特点 拷贝的时候只是拷贝了一份引用,修改拷贝以后的数据会影响原来的数据。
// (2)深拷贝(对象/数组)特点: 拷贝的时候会从堆拷贝一份新的数据,修改拷贝得到的副本的数据不会改变原数据。
//(数组/对象)浅/深拷贝方法:
// 1、数组的拷贝
// 1) 采用扩展运算符
var arr1 = [1, 2, 3, 4];
var arr2 = [...arr1];
arr1[0] = 666;
console.log(arr1); // [666, 2, 3, 4]
console.log(arr2); // [1, 2, 3, 4]
// 2) 数组方法Array.slice()---------Array.slice(开始的索引,结束的索引)并不会修改数组,而是返回一个包含开始索引到结束索引"之前"的子数组,字符串也有slice()方法,用法一致。
var arr1 = [1, 2, 3, 4];
arr2 = arr1.slice(0)
arr1[0] = 666;
console.log(arr1); // [666, 2, 3, 4]
console.log(arr2); // [1, 2, 3, 4]
// 3) 数组方法Array.contact()---------Array.contact(数组1,数组2.../数组元素1,元素2...)并不会修改数组,而是返回一个包含的子数组,字符串也有slice()方法,用法一致。
var arr1 = [1, 2, 3, 4];
arr2 = arr1.concat()
arr1[0] = 666;
console.log(arr1); // [666, 2, 3, 4]
console.log(arr2); // [1, 2, 3, 4]
// 2、对象的拷贝
// 1) Object.assign(obj) 拷贝:当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。 ————————————————————Object.assign(target, ...sources);
var obj = {
name: 'zs', // 一级属性
brother: {
name: 'ls', // 二级属性
friend: {
name: 'ww' // 多级属性
}
}
}
var obj1 = Object.assign(obj);
console.log(obj1);
// 2) 封装函数拷贝:通过for(var k in obj)遍历对象,将简单数据类型实现赋值拷贝,通过条件判断数据类型,结合函数递归实现深层拷贝,从而达到深拷贝。
// !!! 通过判断数据类型,可以实现不管数组/对象都能统统(深)拷贝
// 方法1.遍历方法1(和方法2一致,封装函数而已)
function deepClone(target) {
let result
if (typeof target === 'object') {
if (Array.isArray(target)) {
result = []
for (let i in target) {
result.push(deepClone(target[i]))
}
} else if (target === null) {
result = target
} else if (target.constructor === RegExp) {
result = target
} else if (target.constructor === Date) {
result = target
} else {
result = {}
for (let i in target) {
result[i] = deepClone(targer[i])
}
}
} else if (typeof target === 'function') {
// 如果是函数
result = new Function('return ' + target.toString())
} else {
// 如果是基本数据类型,如number、string、boolean、undefined
result = target
}
return result
}
// 法2:遍历方法2
function deepCopy(newObj, oldObj) {
for (var k in oldObj) {
// 判断我们的属性属于那种数据类型
// 1. 获取属性值 oldObj[k]
var item = oldObj[k];
// 2. 判断这个值是否是数组
if (item instanceof Array) {
newObj[k] = [];
deepCopy(newObj[k], item);
} else if (item instanceof Object) {
// 3. 判断这个值是否是对象
newObj[k] = {};
deepCopy(newObj[k], item);
} else {
// 4. 属于简单数据类型
newObj[k] = item;
}
}
return newObj
}
// 方法3 通过转成JSON字符串再转回来(序列化--反序列化),前提是:要转化的对象符合**json数据类型**的格式:函数不行。
//深拷贝
function deepClone(data) {
let newData = JSON.stringify(data),
dataClone = JSON.parse(newData);
return dataClone;
};
//测试
let arr = [1, 2, 3],
newData = deepClone(arr);
arr[0] = 2;
console.log(arr, newData) //[2,2,3] [1,2,3]
---------------2021.06.03发布于掘金 Qiang
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END