答案:
JS数据类型分为基本数据类型和引用数据类型,基本数据类型保存的是值,引用类型保存的是引用地址(this指针)。浅拷贝共用一个引用地址,深拷贝会创建新的内存地址。
浅拷贝方法
-
直接对象复制
-
Object.assign
深拷贝
-
JSON.stringify转为字符串再JSON.parse
-
深度递归遍历
详细解析:
基本数据类型:string、number、boolean、undefined、null
引用数据类型:object、array、function
浅拷贝,拿人手短,变了;深拷贝,自食其力,不变。
一、浅拷贝
1. 直接对象复制
let a = [0,1,2,3,4],
b = a;
console.log(a === b);
a[0] = 1;
console.log(a,b);
结果:
2. Object.assign:实现浅拷贝及一层的深拷贝
对象的合并 ES6中的 Object.assign(),第一个参数必须是个空对象。
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
注意点!严格来说,Object.assign() 既不是深拷贝,也不是浅拷贝——而是第一级属性深拷贝,第一级以下的级别属性浅拷贝。
let obj1 = {
a: { b: 1},
c: 2
}
let obj2 = Object.assign({},obj1)
obj2.a.b = 3; //第二层,obj1变了,是浅拷贝
obj2.c = 3; //第一层,obj1不变,是深拷贝
console.log(obj1);
console.log(obj2);
结果:
二、深拷贝
1. JSON.stringify转为字符串再JSON.parse
JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象
function deepClone(obj) {
let _obj = JSON.stringify(obj)
let objClone = JSON.parse(_obj)
return objClone
}
let a = [0, 1, [2, 3], 4]
let b = deepClone(a)
a[0] = 1
a[2][0] = 1
console.log(a) // [1,1,[1,3],4]
console.log(b) // [0,1,[2,3],4]
结果:
缺点:当值为undefined、function、symbol 会在转换过程中被忽略
2. 深度递归遍历
基本思路:判断obj 是基本类型就简单赋值,对象(数组)的话 ,创建一个空[ ](obj是对象)或空{ }(obj是对象),再判断obj的属性有没有对象(数组),有递归调用,没有简单赋值,直到全部赋值完毕,返回赋值后的objClone
function deepClone(obj) {
let objClone = Array.isArray(obj) ? [] : {} //根据类型制造一个新的数组或对象 Array.isArray判断是否是数组
if (obj && typeof obj === 'object') {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 判断obj子元素是否为对象,如果是对象,递归复制
if (obj[key] && typeof obj[key] === 'object') {
objClone[key] = deepClone(obj[key])
// 如果是基本数据类型,只是简单的复制
} else {
objClone[key] = obj[key]
}
}
}
}
return objClone
}
let a = [1,2,3,4]
let b = deepClone(a)
a[0] = 2
console.log(a) // [2,2,3,4]
console.log(b) // [1,2,3,4]
结果:
3. jquery实现深拷贝
jquery 提供一个 $.extend
可以用来做深拷贝;
var array1 = [1,2,3,4];
var array2 = $.extend(true,[],array1); // true为深拷贝,false为浅拷贝
console.log(array1 === array2); // false