我用射击延长了shat。延伸后,为什么修改镜头会改变?
var shat = [{bang:true}, {bumm: false}, {bong: false}]
var shot = [{bang:false}, {bumm: false}, {bong: false}]
$.extend(shat, shot)
shot[0].bang = true
console.log("shat", shat)
// prints
Object
bang: true // why is this true?
Object
bumm: false
Object
bong: false
我假设创建了一个引用,或者在shot [0] .bang = true之后由于某种原因发生了扩展。问题是,我想在扩展后修改镜头,但当然不希望它对shat有任何影响。任何想法为什么会发生这种情况以及我可以采取哪些措施来避免这种情况?
请参阅jSfiddle测试用例:http://jsfiddle.net/yEnph/3/
答案 0 :(得分:5)
默认情况下,$.extend
只是浅层复制属性*。这不是很令人兴奋。
在这种情况下,扩展属性为“0”,“1”,“2”等,因此扩展后 shat[0] === shot[0]
为真 如果两者都评估相同的对象,则仅的情况。因为它们是同一个对象然后......好吧,将它变异一个地方就会变异无处不在。
要将它们分开考虑“深层复制”(请参阅调用jQuery.extend的不同方法)。我提到的另一种方法,因为它也可以在其他上下文中使用,是序列化对象然后反序列化它 - 例如与JSON。
var shat = [{bang:true}, {bumm: false}, {bong: false}]
var shot = [{bang:false}, {bumm: false}, {bong: false}]
$.extend(true, shat, shot) // use "deep copy"
shat[0] === shot[0] // false; different objects now so...
shot[0].bang = "boom" // ...this will not affect the object named by shat[0]
shot[0].bang // "boom"
shat[0].bang // false
快乐的编码。
*也就是说,对于源对象中的每个属性p
,它只是target[p] = source[p]
。请记住,在JavaScript中,数组只是具有神奇length
的对象的特殊子类型:索引n处的值由属性“n”命名。
答案 1 :(得分:2)
从jQuery文档http://api.jquery.com/jQuery.extend/看起来,$ .extend只会对象进行扩充,而不会对数组进行扩充。在该示例中,您的shat
变量从未更改过。
答案 2 :(得分:1)
有趣的是,它完全不起作用,并不知道extend
在数组上工作。
这样做的原因是两个数组都包含对同一对象的引用。这也是警告“新”的原因:
var a = { test: "one"};
var b = a;
a.test="new";
alert(b.test);
两个变量都引用同一个对象,因此编辑对象会更新它们引用的对象。
答案 3 :(得分:0)
如果获取了密钥,则扩展只会覆盖属性:
var a = {
hello: "kitty"
},
b = {
hello: "world"
}
$.extend( a, b );
console.log( a );
//Object
//hello: "world"
由于数组只是具有数字属性名称的对象,因此除了"hello"
为"0"
之外,您将使用相同的原则替换它们,依此类推。
因为您有对象而不是基元,shat
获取shot
的对象,所以它们会被重写,因此原始的shat
对象会丢失。因此,修改shot
的对象将修改shat
的对象,因为它们是相同的对象。