我可以使用解构来创建深拷贝吗?
Can I use Destructuring to create a deep copy?
基本上我想得到一个浅深拷贝,不会使用解构改变我的主要对象。
let a = {
name: 'lala',
testArray: [1,2,3],
object: {
name: 'object',
array: [4,5,6]
}
};
const {name, testArray, object} = a;
object.array = [...object.array, 0];
console.log(a.object.array);
let b = {
object2: {
name: 'object',
array: [4,5,6]
}
};
const object2 = {...b.object2};
object2.array = [...object2.array, 0];
console.log(b.object2.array);
我制作了一个 jsfiddle(为了更容易复制),提供了我编写的代码。
https://jsfiddle.net/5z71Lbja/
问题是,当我使用第一种方法(解构)更改 "child" 对象时,主对象的数组也会发生变化。第二种方法工作正常,但我很好奇我是否可以使用解构实现相同的结果。
你不能用解构创建新对象,不。您只能挑选出源上存在的值,不能对它们执行转换。 (你可以改变你使用的变量名,但你不能转换值。)我经常想,但你不能(至少,目前不能)。
有多种 jump-through-the-hoops 方法可以实现,但实际上最简单的方法是分别制作数组的浅表副本。
一个更简单的例子:
const obj = {
foo: "bar",
array: [1, 2, 3]
};
const {foo} = obj;
const array = obj.array.slice(); // or: = [...obj.array];
obj.array[0] = "one";
console.log(obj.array[0]); // "one"
console.log(array[0]); // 1
直接是不行的
let { object } = a;
object = {...object}; // Object.assign({}, object); <<
object.array = [0, ...object.array, 0];
console.log(object.array); // [0, 4, 5, 6, 0]
console.log(a.object.array); // [4, 5, 6]
回答
您可以通过函数或直接使用 Proxy
对象来实现。
在 Destruct 期间使用函数:
Proxy
对象取target
对象,handler
.
A handler
允许您设置某些条件,例如 get
和 set
,这些条件可以改变数据 returned 给用户的方式。为此,我们将使用 get
。
在下面的处理程序中,我们更改了 get
功能。我们检查 target[prop]
return 是 Array
还是 Object
。如果是这样,我们会在内存中创建一个副本并 return 代替引用。如果它不是 Array
或 Object
我们简单地 return 原始值(字符串,数字等)
let copyHandler = {
get: function( target, prop, receiver ) {
let value = target[ prop ];
if ( Array.isArray( value ) ) return value.slice( 0 );
if ( typeof value === "object" && value.constructor.name === "Object" ) return Object.assign( {}, value );
return value;
}
}, getCopy = obj => new Proxy(obj, copyHandler);
利用 getCopy
函数作为我们的解构 middle-man,我们可以确定我们所有的值 return 新引用:
const {
name,
testArray,
object
} = getCopy(a);
object.array = [...object.array, 0];
console.log(a.object.array); // [4,5,6]
console.log(object.array); // [4,5,6,0]
示例:
let copyHandler = {
get: function( target, prop, receiver ) {
let value = target[ prop ];
if ( Array.isArray( value ) ) return value.slice( 0 );
if ( typeof value === "object" && value.constructor.name === "Object" ) return Object.assign( {}, value );
return value;
}
}, getCopy = obj => new Proxy(obj, copyHandler);
let a = {
name: 'lala',
testArray: [ 1, 2, 3 ],
object: {
name: 'object',
array: [ 4, 5, 6 ]
}
};
const {
name,
testArray,
object
} = getCopy(a);
object.array = [...object.array, 0];
console.log(a.object.array); // [4,5,6]
console.log(object.array); // [4,5,6,0]
或者,我们可以直接在 Declaration/Initialization/Reception:
直接在这个意义上意味着我们可以将对象设置为 return 仅在解构声明期间的副本。
我们通过使用 Proxy
和 middle-man 函数来执行与上述类似的操作。
注意: middle-man 函数不是必需的,但它有助于使事情井井有条。
let destructHandler = {
get: function( target, prop, receiver ) {
if(!this.received) this.received = new Set();
let value = target[ prop ];
if(this.received.has(prop)) return value;
this.received.add(prop);
if ( Array.isArray( value ) ) return value.slice( 0 );
if ( typeof value === "object" && value.constructor.name === "Object" ) return Object.assign( {}, value );
return value;
}, destructable = obj => new Proxy(obj, destructHandler);
这里的区别是我们的 get
处理程序使用 Set
来确定 属性 是否已经被抓取过一次。
它会 return 在第一次请求引用时复制 属性(Array
或 Object
)。它仍然会 return 正常的任何原始值。
这意味着在 declaring/initialization/reception 对象上,您可以应用 destructable
代理,然后立即使用 destruct 从该对象中提取副本。
初始化示例代码:
let a = destructable({
name: 'lala',
testArray: [ 1, 2, 3 ],
object: {
name: 'object',
array: [ 4, 5, 6 ]
}
});
解构示例:
const {
name,
testArray,
object
} = a;
object.array = [...object.array, 0];
console.log(a.object.array); // [4,5,6]
console.log(object.array); // [4,5,6,0]
示例:
let destructHandler = {
get: function( target, prop, receiver ) {
if(!this.received) this.received = new Set();
let value = target[ prop ];
if(this.received.has(prop)) return value;
this.received.add(prop);
if ( Array.isArray( value ) ) return value.slice( 0 );
if ( typeof value === "object" && value.constructor.name === "Object" ) return Object.assign( {}, value );
return value;
}
}, destructable = obj => new Proxy(obj, destructHandler);
let a = destructable({
name: 'lala',
testArray: [ 1, 2, 3 ],
object: {
name: 'object',
array: [ 4, 5, 6 ]
}
});
const {
name,
testArray,
object
} = a;
object.array = [...object.array, 0];
console.log(object.array); // [4,5,6,0]
console.log(a.object.array); // [4,5,6]
希望对您有所帮助!编码愉快!
我认为可以尝试使用以下代码对对象进行深度复制,我使用了解构。
function deepcopy(obj) {
let { ...data
} = obj;
let newObj = { ...data
}
// deleting one key (just to show that it doesn't affect original obj)
delete newObj.a
console.log("param obj ", obj);
return newObj;
}
const obj = {
a: 1,
b: 2,
c: 3
}
console.log("original obj ", obj);
console.log("copy newObj", deepcopy(obj));
console.log("original obj ", obj);
希望对您有所帮助!!! :)
基本上我想得到一个浅深拷贝,不会使用解构改变我的主要对象。
let a = {
name: 'lala',
testArray: [1,2,3],
object: {
name: 'object',
array: [4,5,6]
}
};
const {name, testArray, object} = a;
object.array = [...object.array, 0];
console.log(a.object.array);
let b = {
object2: {
name: 'object',
array: [4,5,6]
}
};
const object2 = {...b.object2};
object2.array = [...object2.array, 0];
console.log(b.object2.array);
我制作了一个 jsfiddle(为了更容易复制),提供了我编写的代码。
https://jsfiddle.net/5z71Lbja/
问题是,当我使用第一种方法(解构)更改 "child" 对象时,主对象的数组也会发生变化。第二种方法工作正常,但我很好奇我是否可以使用解构实现相同的结果。
你不能用解构创建新对象,不。您只能挑选出源上存在的值,不能对它们执行转换。 (你可以改变你使用的变量名,但你不能转换值。)我经常想,但你不能(至少,目前不能)。
有多种 jump-through-the-hoops 方法可以实现,但实际上最简单的方法是分别制作数组的浅表副本。
一个更简单的例子:
const obj = {
foo: "bar",
array: [1, 2, 3]
};
const {foo} = obj;
const array = obj.array.slice(); // or: = [...obj.array];
obj.array[0] = "one";
console.log(obj.array[0]); // "one"
console.log(array[0]); // 1
直接是不行的
let { object } = a;
object = {...object}; // Object.assign({}, object); <<
object.array = [0, ...object.array, 0];
console.log(object.array); // [0, 4, 5, 6, 0]
console.log(a.object.array); // [4, 5, 6]
回答
您可以通过函数或直接使用 Proxy
对象来实现。
在 Destruct 期间使用函数:
Proxy
对象取target
对象,handler
.
A handler
允许您设置某些条件,例如 get
和 set
,这些条件可以改变数据 returned 给用户的方式。为此,我们将使用 get
。
在下面的处理程序中,我们更改了 get
功能。我们检查 target[prop]
return 是 Array
还是 Object
。如果是这样,我们会在内存中创建一个副本并 return 代替引用。如果它不是 Array
或 Object
我们简单地 return 原始值(字符串,数字等)
let copyHandler = {
get: function( target, prop, receiver ) {
let value = target[ prop ];
if ( Array.isArray( value ) ) return value.slice( 0 );
if ( typeof value === "object" && value.constructor.name === "Object" ) return Object.assign( {}, value );
return value;
}
}, getCopy = obj => new Proxy(obj, copyHandler);
利用 getCopy
函数作为我们的解构 middle-man,我们可以确定我们所有的值 return 新引用:
const {
name,
testArray,
object
} = getCopy(a);
object.array = [...object.array, 0];
console.log(a.object.array); // [4,5,6]
console.log(object.array); // [4,5,6,0]
示例:
let copyHandler = {
get: function( target, prop, receiver ) {
let value = target[ prop ];
if ( Array.isArray( value ) ) return value.slice( 0 );
if ( typeof value === "object" && value.constructor.name === "Object" ) return Object.assign( {}, value );
return value;
}
}, getCopy = obj => new Proxy(obj, copyHandler);
let a = {
name: 'lala',
testArray: [ 1, 2, 3 ],
object: {
name: 'object',
array: [ 4, 5, 6 ]
}
};
const {
name,
testArray,
object
} = getCopy(a);
object.array = [...object.array, 0];
console.log(a.object.array); // [4,5,6]
console.log(object.array); // [4,5,6,0]
或者,我们可以直接在 Declaration/Initialization/Reception:
直接在这个意义上意味着我们可以将对象设置为 return 仅在解构声明期间的副本。
我们通过使用 Proxy
和 middle-man 函数来执行与上述类似的操作。
注意: middle-man 函数不是必需的,但它有助于使事情井井有条。
let destructHandler = {
get: function( target, prop, receiver ) {
if(!this.received) this.received = new Set();
let value = target[ prop ];
if(this.received.has(prop)) return value;
this.received.add(prop);
if ( Array.isArray( value ) ) return value.slice( 0 );
if ( typeof value === "object" && value.constructor.name === "Object" ) return Object.assign( {}, value );
return value;
}, destructable = obj => new Proxy(obj, destructHandler);
这里的区别是我们的 get
处理程序使用 Set
来确定 属性 是否已经被抓取过一次。
它会 return 在第一次请求引用时复制 属性(Array
或 Object
)。它仍然会 return 正常的任何原始值。
这意味着在 declaring/initialization/reception 对象上,您可以应用 destructable
代理,然后立即使用 destruct 从该对象中提取副本。
初始化示例代码:
let a = destructable({
name: 'lala',
testArray: [ 1, 2, 3 ],
object: {
name: 'object',
array: [ 4, 5, 6 ]
}
});
解构示例:
const {
name,
testArray,
object
} = a;
object.array = [...object.array, 0];
console.log(a.object.array); // [4,5,6]
console.log(object.array); // [4,5,6,0]
示例:
let destructHandler = {
get: function( target, prop, receiver ) {
if(!this.received) this.received = new Set();
let value = target[ prop ];
if(this.received.has(prop)) return value;
this.received.add(prop);
if ( Array.isArray( value ) ) return value.slice( 0 );
if ( typeof value === "object" && value.constructor.name === "Object" ) return Object.assign( {}, value );
return value;
}
}, destructable = obj => new Proxy(obj, destructHandler);
let a = destructable({
name: 'lala',
testArray: [ 1, 2, 3 ],
object: {
name: 'object',
array: [ 4, 5, 6 ]
}
});
const {
name,
testArray,
object
} = a;
object.array = [...object.array, 0];
console.log(object.array); // [4,5,6,0]
console.log(a.object.array); // [4,5,6]
希望对您有所帮助!编码愉快!
我认为可以尝试使用以下代码对对象进行深度复制,我使用了解构。
function deepcopy(obj) {
let { ...data
} = obj;
let newObj = { ...data
}
// deleting one key (just to show that it doesn't affect original obj)
delete newObj.a
console.log("param obj ", obj);
return newObj;
}
const obj = {
a: 1,
b: 2,
c: 3
}
console.log("original obj ", obj);
console.log("copy newObj", deepcopy(obj));
console.log("original obj ", obj);
希望对您有所帮助!!! :)