数字化转型|广州蓝景分享—谈谈JavaScript 的对象复制( 二 )


console.log(newObj); // { a: 1 b: { c: 2
obj.a = 10;
console.log(obj); // { a: 10 b: { c: 2
console.log(newObj); // { a: 1 b: { c: 2
newObj.a = 20;
console.log(obj); // { a: 10 b: { c: 2
console.log(newObj); // { a: 20 b: { c: 2
newObj.b.c = 30;
console.log(obj); // { a: 10 b: { c: 30
console.log(newObj); // { a: 20 b: { c: 30
// Note: newObj.b.c = 30; Read why..
为什么obj.b.c = 30?
嗯 , 这是Object.assign()的一个陷阱 。 Object.assign只制作浅拷贝 。 newObj.b和obj.b两者共享对同一个对象的相同引用 , 因为没有制作单独的副本 , 而是复制了对同一个对象的引用 。 对那个对象的任何属性所做的任何更改都适用于使用该对象的所有引用 。
注意:原型链上的属性和不可枚举的属性不能复制 。看这里:
let someObj = {
a: 2

let obj = Object.create(someObj {
b: {
value: 2

c: {
value: 3
enumerable: true

);
let objCopy = Object.assign({ obj);
console.log(objCopy); // { c: 3

  • someObj在obj的原型链上 , 所以它不会被复制 。
  • 属性b是不可枚举的属性 。
  • 属性c有一个可枚举的属性描述符 , 允许其成为可枚举 。 这就是属性c被复制的原因 。
深度拷贝对象
深拷贝将复制它遇到的每个对象 。 副本和原始对象不会共享任何内容 。 下面是使用Object.assign()遇到的问题的解决方法 。
使用JSON.parse(JSON.stringify(object));
这解决了我们之前遇到的问题 。 现在newObj.b有一个副本而不是引用!这是一种深度复制对象的方法 。 请看例子:
let obj = {
a: 1
b: {
c: 2


let newObj = JSON.parse(JSON.stringify(obj));
obj.b.c = 20;
console.log(obj); // { a: 1 b: { c: 20
console.log(newObj); // { a: 1 b: { c: 2(New Object Intact!)
陷阱
不幸的是 , 此方法不能用于复制用户定义的对象方法 。
复制对象方法
到目前为止的示例中 , 我们还不能复制对象的方法 。 现在让我们尝试一下 , 如何来复制对象的方法 。
let obj = {
name: 'scotch.io'
exec: function exec() {
return true;


let method1 = Object.assign({ obj);
let method2 = JSON.parse(JSON.stringify(obj));
console.log(method1); //Object.assign({ obj)
/* result
{
exec: function exec() {
return true;

name: \"scotch.io\"

*/
console.log(method2); // JSON.parse(JSON.stringify(obj))
/* result
{
name: \"scotch.io\"

*/
表明Object.assign()可以用来复制对象方法 ,
而JSON.parse(JSON.stringify(obj))却不能 。
复制circular对象
circular对象是具有引用自身属性的对象 。 让我们使用复制对象的方法来复制circular对象 , 看看它是否有效 。
使用JSON.parse(JSON.stringify(object))
试试JSON.parse(JSON.stringify(object)):
// circular object
let obj = {
a: 'a'
b: {
c: 'c'
d: 'd'


obj.c = obj.b;
obj.e = obj.a;
obj.b.c = obj.c;
obj.b.d = obj.b;
obj.b.e = obj.b.c;
let newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj);
结果:
JSON.parse(JSON.stringify(obj))显然不适用于circular对象 。
使用Object.assign()
再试试Object.assign():
// circular object
let obj = {
a: 'a'
b: {
c: 'c'
d: 'd'


obj.c = obj.b;
obj.e = obj.a;
obj.b.c = obj.c;
obj.b.d = obj.b;
【数字化转型|广州蓝景分享—谈谈JavaScript 的对象复制】