繁体   English   中英

数组属性上Object.create的怪异行为

[英]Weird behaviour with Object.create on array properties

使用Object.create()和原型对象创建新对象时,新对象似乎对数组属性保留对原型的引用。

范例程式码

var obj = { color: ['white'], cat: 'Kitty', state: {}};
obj2 = Object.create(obj);
obj2.color.push('blue');
obj2.color.push('red');
obj2.color.push('yellow');
obj2.cat = 'Fluffy';
obj2.state = {complete: false};
console.log('obj2 color = ' + JSON.stringify(obj2.color) + ', obj2.cat = ' + obj2.cat + ', state = ' + JSON.stringify(obj2.state));
console.log('obj color = ' + JSON.stringify(obj.color) + ', obj.cat = ' + obj.cat + ', state = ' + JSON.stringify(obj.state));

结果

obj2 color = ["white","blue","red","yellow"], obj2.cat = Fluffy, state = {"complete":false}
obj color = ["white","blue","red","yellow"], obj.cat = Kitty, state = {}

新obj2中的字符串属性“ cat”具有预期的行为,并且与原型对象“ obj”中的该属性无关。 与对象属性“状态”相同。

但是,在数组“颜色”上,当我更改数组时,它也在原型对象上也发生了变化!

这是用Java编写的吗? 对我而言,这是来自面向对象的背景,这完全是意外的。 我认为这没有逻辑。 数组有什么不同?

如果像字符串这样的值类型在行为上与对象属性不同,但它们却没有(如本例所示),则我什至可以看到一些逻辑-数组的行为也有所不同。

分配给对象属性:

obj.xyz = "hello world";

总是直接在目标对象上更新(如果需要,创建)属性。

但是,将值推入数组并不构成“分配给对象属性”。 请注意,鉴于您的代码,

obj2.color = ["green"];

将直接在目标对象上创建一个新的“颜色”属性。

在声明中

obj2.color.push('blue');

在原型对象的查找操作中找到“颜色”属性。 然后,通过该对象引用(对原型上“ color”属性的引用),查找“ push”属性。 最终可以在Array.prototype对象上找到。 然后将该值称为函数。 在此过程中,没有任何事情涉及更新“ obj2”上的属性值。

原型上的“颜色”属性是数组并不是特别特殊。 对于任何对象引用,您都会看到类似的效果。 考虑:

var proto = { obj: { a: 1, b: 2 } };
var obj2 = Object.create(proto);
obj2.obj.a = 3;

这将更改原型中的“ obj”对象。

最后应该指出的是, 通常原型是函数引用的来源,而不是简单的值。

TLDR:设置对象的属性可直接在该对象上设置它。 获取属性沿原型链上升。

 obj2.color

那得到原型的阵列。

除了Pointy解释清楚的答案外 ,您还可以执行类似的操作来创建深度克隆的对象。

但是请注意,正如Pointy所说,这可能不适用于“所有”对象。

var new_obj = JSON.parse(JSON.stringify(old_obj));`

堆栈片段

 var obj = { color: ['white'], cat: 'Kitty', state: {}}; var obj2 = JSON.parse(JSON.stringify(obj)); obj2.color.push('blue'); obj2.color.push('red'); obj2.color.push('yellow'); obj2.cat = 'Fluffy'; obj2.state = {complete: false}; console.log('obj2 color = ' + JSON.stringify(obj2.color) + ', obj2.cat = ' + obj2.cat + ', state = ' + JSON.stringify(obj2.state)); console.log('obj color = ' + JSON.stringify(obj.color) + ', obj.cat = ' + obj.cat + ', state = ' + JSON.stringify(obj.state)); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM