先看JS的数据类型
- 基本类型:Undefined、Null、Boolean、Number 和 String
- 引用类型:Object
复制变量值
基本类型
在变量对象上创建一个新值,然后把该值复制到为新值分配的位置上。
来看一个例子:
var num1 = 5;
var num2 = num1;
num1
中保存的值是5
。当使用 num1
初始化num2
时,num2
也保存了值 5
。但是num1
中的5
和num2
中的5
是完全独立的,该值只是 num1
中5
的一个副本。此后这两个变量可以参加任何操作而不会相互影响。
引用类型
从一个变量向另一个新变量复制引用类型的值,其实复制的是指针,最终两个变量最终都指向同一个对象。
var obj1 = new Object();
var obj2 = obj1;
obj1.name = "Jack";
console.log("obj2.name"); // 'Jack'
改变其中一个变量的值会影响到另一个变量。
深浅拷贝
假设 A 复制了 B :
如果改变其中一个变量的值会影响到另一个变量,那么就是浅拷贝;
如果这两个变量可以参加任何操作而不会相互影响,那就是深拷贝。
简单的来说,就是如果改变 A 的值 B 也改变了,就是浅拷贝,B没变就是深拷贝。
浅拷贝
1. 直接赋值
2. Object.assign()
Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。
var obj1 = {
name: "Jack"
};
var obj2 = Object.assign({}, obj1);
obj1.name = "Ann";
console.log(obj2.name); // 'Jack'
这个表面上看是实现了深拷贝,但是如果对象中嵌套对象,Object.assign()只能拷贝一层
var obj1 = {
name: "Jack",
friends: {
name: "Bob",
age: 16
}
};
var obj2 = Object.assign({}, obj1);
obj2.friends.name = "Ann";
console.log(obj1.friends.name); // 'Ann'
由此可见obj1.friends
和obj2.friends
还是指向同一个对象。
3. Array 的 concat 和 slice 方法
深拷贝
1. JSON 对象的 parse 和 stringify
var obj1 = {
name: "Jack",
friends: {
name: "Bob",
age: 16
}
};
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.name = 'Ann';
obj2.friends.name = 'Jone';
console.log(obj1.name); // 'Jack'
console.log(obj1.friends.name); // 'Bob'
2. 递归
function deepClone(obj) {
if(typeof obj !== Object) return;
let copy = obj instanceof Array ? [] : {};
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
}
}
return copy;
}