由 Object.Assign() 函数生成的复制对象具有副作用
Copied object generated by Object.Assign() function has side effect?
我有一个名为result的对象,它由两个对象组成,如下所示:
const a = {bar: {baz: 2}};
var b = {foo: 1};
var result = Object.assign({}, a, b);
console.log(result, a, b);
// result -> {bar: {baz: 2}, foo: 1}
// a -> {bar: {baz: 2}}
// b -> {foo: 1}
现在,我正在更改结果对象的 bar 属性,例如:
result.bar.baz = 3;
result.foo = 4;
console.log(result, a, b);
// result -> {bar: {baz: 3}, foo: 4}
// a -> {bar: {baz: 3}} intresting part
// b -> {foo: 1} intresting, too!
(您可以将代码复制并粘贴到javascript控制台,以便顺便查看两种情况的结果)
这里有两件奇怪的事情。第一个是我正在更改结果对象的属性,但常量对象 a 的属性也会更改。即使第一个是 Object.assign 函数的情况,我该如何更改常量变量?假设尽管常量变量突变,情况确实如此,那么为什么属性foo的变化没有反映到对象b上呢?我这样做是因为我通常使用 Object.assign 来复制对象,但我想这是该函数非常奇怪的问题。对这个案子有什么想法吗?谢谢。
使用 const
声明变量只会防止它被更改为另一个值。它不会阻止该值引用的数据发生更改。
const foo = {prop: 'bar'};
foo.prop = 'baz'; // Works well
foo = 'baz'; // TypeError: invalid assignment to const `foo'
如果要阻止对象被更改,可以将其冻结。
Object.freeze(foo);
foo.prop = 'buz'; // TypeError: "prop" is read-only
但是,这只会影响自己的财产。如果其中一个对象的值是另一个对象,则它不会被冻结。
Object.assign
也是如此。它只复制自己的属性,如果它们的值是一个对象,它不会"克隆"它。也就是说,引用仍将相同,并且将反映更改。
如果要深度克隆对象,请参阅克隆对象的最有效方法是什么?
Object.assign 将起作用,但添加了陷阱,即如果您要从中分配的任何属性包含对象作为值,它不会创建该对象的副本,因此引用不会更改,创建对象中的属性将指向相同的嵌套对象。
JavaScript 中的常量也可能具有欺骗性,只要您不尝试将其重新分配给新对象或其他原语,您就可以在"const"对象中添加和删除属性。
数组也会发生同样的情况,您可以创建一个"const"数组,但将其推开。
https://jsfiddle.net/eu9yg37s/6/只是我为了展示我的意思而胡闹的东西。
const a = {bar: {baz: 2}};
var b = {foo: 1};
// Example of customizer function that may take into account nested objects and properly copy them using lodash 4.x
var customizer = function(objValue, srcValue) {
if (typeof srcValue === 'object' && typeof srcValue !== null) {
return _.assignWith({}, srcValue, customizer);
}
return _.isUndefined(objValue) ? srcValue : objValue;
}
// This calls assign, but will invoke the customizer function
var result = _.assignWith({}, a, b, customizer);
result.bar.baz = 3;
result.foo = 4;
console.log(result, a, b);
// 'Constant' Array Example
const hi = [true, false, 'hi'];
hi[2] = 23;
console.log('hi.pop', hi.pop());
console.log('hi', hi);
// These will error, uncomment out to see it errors on any of these attempts
//hi = 3;
//hi = 'no';
hi = [true, false, 23];
//hi = false;
//hi = {};
更改不会反映在 b 中,因为它在分配操作期间不是嵌套对象,因此我们创建的对象中的属性 foo 指向新的基元 1
- 何时需要使用Object.assign()方法来复制对象的实例
- lodash:深度复制对象,但不是所有属性
- 复制对象,然后更新 JSON 对象中的值
- 如何使用 jquery 按值复制对象
- 如何在 CoffeeScript 中克隆/复制对象的实例
- 为什么 jQuery 扩展深拷贝不递归复制对象
- 使用 jQuery 深层复制对象数组属性值
- 由 Object.Assign() 函数生成的复制对象具有副作用
- 复制对象后删除对象属性时出现奇怪的行为
- angular.copy无法复制对象
- 在JavaScript中复制对象属性
- Javascript:如何复制对象并保持其原型链
- 如何在另一个对象中复制对象属性
- 如何在React中复制对象之间的嵌套状态
- 如何访问或复制对象的字符串值
- 通过引用复制对象是否有实际用途
- 如何在不调用构造函数的情况下复制对象及其原型链?
- 如何在javascript中深度复制对象作为对象而不是数组
- 复制对象的属性,而不必重复所有变量名
- VueJs如何从v-repeat复制对象