谈这个话题特指javascript中的对象,我们使用赋值的语法来定义一个对象,其实只是获取了这个对象的引用
let user = { name: "John" };
这里的user变量只是指向了对象,是对象的一个引用
如果我们再定义一个变量,并且把user赋值给变量
let user = { name: "John" }; let admin = user; // copy the reference
这里的admin也指向了变量,user和admin都是对象的引用
let user = { name: 'John' }; let admin = user; admin.name = 'Pete'; // changed by the "admin" reference alert(user.name); // 'Pete', changes are seen from the "user" reference
因为指向的是一个对象,所以通过admin来改变对象的属性,再用user去访问属性时会得到一个值,是改变后的Pete
let a = {}; let b = a; // copy the reference alert( a == b ); // true, both variables reference the same object alert( a === b ); // true
因为a和b都指向相同的对象,所以他们的值和类型都相同
let a = {}; let b = {}; // two independent objects alert( a == b ); // false
a和b是两个对象,所以他们不相等
变量定义和赋值不能实现对象的拷贝,那我想复制出一模一样的对象怎么办?
let user = { name: "John", age: 30 }; let clone = {}; // the new empty object // let's copy all user properties into it for (let key in user) { clone[key] = user[key]; } // now clone is a fully independent object with the same content clone.name = "Pete"; // changed the data in it alert( user.name ); // still John in the original object
可以迭代对象的属性做赋值,但是这样稍显麻烦,javascript有现成的API可以做到这一件事
Object.assign(dest, [src1, src2, src3...])
通过这个API就可以实现将对象的属性进行合并赋值给新的对象
例如:
let user = { name: "John" }; let permissions1 = { canView: true }; let permissions2 = { canEdit: true }; // copies all properties from permissions1 and permissions2 into user Object.assign(user, permissions1, permissions2); // now user = { name: "John", canView: true, canEdit: true }
如果要是遇到属性相同会进行覆盖
let user = { name: "John" }; Object.assign(user, { name: "Pete" }); alert(user.name); // now user = { name: "Pete" }
我们也可以采用简写的语法
let user = { name: "John", age: 30 }; let clone = Object.assign({}, user);
这样就复制出一个对象来,clone就是复制后的对象
如果对象的属性也是对象,那这种情况复制会出现什么情况呢?
let user = { name: "John", sizes: { height: 182, width: 50 } }; alert( user.sizes.height ); // 182
let user = { name: "John", sizes: { height: 182, width: 50 } }; let clone = Object.assign({}, user); alert( user.sizes === clone.sizes ); // true, same object // user and clone share sizes user.sizes.width++; // change a property from one place alert(clone.sizes.width); // 51, see the result from the other one
这样的复制叫浅拷贝,因为只是拷贝了对象的引用,如果原对象的值发生改变会影响到复制出来的新对象的值,这样就造成了混乱。所以当对象的属性也是对象时,使用浅拷贝的API就行不通了,这个时候我们需要使用深拷贝。
var objects = [{ 'a': 1 }, { 'b': 2 }]; var deep = _.cloneDeep(objects); console.log(deep[0] === objects[0]); // => false
深拷贝会递归的迭代属性,属于彻底的复制出一个新的对象来。
另外还需注意的就是const
const user = { name: "John" }; user.name = "Pete"; // (*) alert(user.name); // Pete
使用const后只是说这个对象的引用不能改变了,并不意味着对象的属性不可以改变