let a = {
age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2
从上述例子中我们可以发现,如果给一个变量赋值一个对象,那么两者的值会是同一个引用,其中一方改变,另一方也会相应改变。
通常在开发中我们不希望出现这样的问题,我们可以使用浅拷贝来解决这个问题。
浅拷贝:
1、使用 Object.assign
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
2、使用展开运算符(…)
let a = {
age: 1
}
let b = {...a}
a.age = 2
console.log(b.age) // 1
通常浅拷贝就能解决大部分问题了,但是当我们遇到如下情况就需要使用到深拷贝了。
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = {...a}
a.jobs.first = 'native'
console.log(b.jobs.first) // native
浅拷贝只解决了第一层的问题,如果接下去的值中还有对象的话,那么就又回到刚开始的话题了,两者享有相同的引用。要解决这个问题,我们需要引入深拷贝。
深拷贝:
1.纯 JSON 数据对象:使用 JSON 全局对象的 parse
和 stringify
方法。
缺点:不能拷贝函数,并且会丢失原型链。
//JSON.stringify()将对象转成字符串;JSON.parse()将字符串转成对象
let a = { x: 10, y: [20, 5]}
let b = JSON.parse(JSON.stringify(a))
2.jQuery —— $.clone() / $.extend()
$.clone()
:用于 DOM 对象的深复制。
$.extend()
:用于JS 对象的深复制。在 jQuery 中可以通过添加一个参数来实现递归extend。调用$.extend(true, {}, ...)
就可以实现深复制。
//改变y,z中的属性值不会修改原对象
var x = {
a: 1,
b: { f: { g: 1 } },
c: [ 1, 2, 3 ]
};
var y = $.extend({}, x), //shallow copy
z = $.extend(true, {}, x); //deep copy 深拷贝
y.b.f === x.b.f // true
z.b.f === x.b.f // false
y.a=2;
x.a;//1
z.a=3;
x.a;//1
3.ES6中的新方法:Object.create()生成操作
、Object.isPrototypeOf读操作
克隆原始对象自身的值,且保持继承链来克隆它继承的值。
let m1={
a: 1,
b: { f: { g: 1 } },
c: [ 1, 2, 3 ]
};
let n = Object.getPrototypeOf(m);//读取m的原型属性方法
let m2= Object.assign(Object.create(n), origin);//Object.create(n)创建一个新对象{}并继承原对象的原型属性方法
m2.b.f===m1.b.f;//false
m2.a=2;
m1.a;//1