深拷贝:一个变量复制另一个变量的内容,但两个变量之间相互不影响。用通俗的话说就是两个变量只是长的一样,但是不是同一个人。
有深拷贝当然也就会有浅拷贝,浅拷贝比较简单,一个变量复制另一个变量的内容,这个变量是另一个变量的副本。其实俩变量都是同一个人,只是名字不同,有两个名字。
深拷贝的主要应用在引用值的数据类型,像数组、对象的等。这里还牵扯到一个知识点,就是如何区分变量是数组对象还是对象。换句话需要判断变量是[ ]还是{ }。因为在JavaScript中的Array和Object都是对象。
区分Array和Object
var arr = [];
var obj = {};
- instanceof 标识符
a instanceof b
看a的原型链上是否有b的原型
console.log(obj instanceof Object);
console.log(arr instanceof Object);
console.log(obj instanceof Array);
- toString()方法
console.log(Object.prototype.toString.call(obj));
console.log(Object.prototype.toString.call(arr));
- constructor属性
封装深拷贝函数
在上面结束了这些之后,我们再来看怎么去实现深层拷贝。
分析:
- 遍历对象
- 判断对象的属性是不是基本类型值 是——直接复制
- 复杂数据类型需要判断是 {} 还是 [] 创建不同的对象
- 递归 再一次把对象的属性值作为被拷贝对象 进行拷贝
- 直到遇到基本数据类型值递归结束
var obj = {
name: 'lyf',
age: 18,
card: ['visa', 'master'],
wife: {
name: 'xxx',
age: 18
}
}
var objCopy = {};
deepClone(objCopy, obj);
// target拷贝origin对象
function deepClone(target, origin) {
// 初始化变量
var target = target || {},
arrStr = "[object Array]",
toStr = Object.prototype.toString;
for (prop in origin) {
// 判断origin对象的属性是不是自己的 不用拷贝原型上的属性和方法
if (origin.hasOwnProperty(prop)) {
// 判断对象值是引用值类型还是数值类型
if (origin[prop] !== "null" && typeof (origin[prop]) == "object") {
// if (toStr.call(origin[prop]) == arrStr) {
// target[prop] = [];
// } else {
// target[prop] = {};
// }
// 优化
target[prop] = toStr.call(origin[prop]) == arrStr ? [] : {};
} else {
target[prop] = origin[prop];
}
}
}
return target;
}
当我们为任意一个对象添加值时,都不会互相影响。
深拷贝结束!!!!