jQuery 的扩展是否在对象之间创建引用?
我用射击来延长距离。延长后,为什么修改镜头会改变效果?
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 之后创建了一个引用或由于某种原因发生了扩展。问题是,我想在延伸后修改镜头,但当然不想对镜头产生任何影响。有什么想法为什么会发生这种情况以及我可以做些什么来避免这种情况吗?
请参阅 jSfiddle 测试用例: http://jsfiddle.net/yEnph/3/
I am extending shat with shot. After extending, why does modifying shot alter 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
I am assuming a reference is created or the extending is for some reason happening after the shot[0].bang = true. The problem is, I want to modify shot after the extending, but of course dont want to have it any effect on shat. Any ideas why this is happening and what I could do to avoid that?
see jSfiddle testcase: http://jsfiddle.net/yEnph/3/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
默认情况下,
$.extend
仅浅复制属性*。这不是很令人兴奋。在本例中,扩展属性为“0”、“1”、“2”等,因此
shat[0] === shot[0]
为 true扩展后仅两者计算结果为相同对象时的情况。既然它们是同一个对象,那么……好吧,改变一个地方就会改变它各处。为了使它们分开,请考虑“深层复制”(请参阅调用 jQuery.extend 的不同方法)。我提到的另一种方法是序列化对象,然后反序列化它,因为它也可以在其他上下文中使用,例如使用 JSON。
快乐编码。
*也就是说,对于源对象中的每个属性
p
,它仅执行target[p] = source[p]
操作。请记住,在 JavaScript 中,数组只是对象的一种特殊子类型,具有神奇的长度
:索引 n 处的值由属性“n”命名。By default,
$.extend
merely shallow-copies properties*. It's not very exciting.In this case, the extended properties are "0", "1", "2", etc, and thus
shat[0] === shot[0]
is true after extending which is only the case if both evaluate to the same object. Since they are the same object then ... well, mutating it one place mutates it everywhere.To keep them separate consider a "deep copy" (see the different ways to invoked jQuery.extend). Another approach, that I mention because it can also be used in other contexts, is to serialize the object and then de-serialize it -- e.g. with JSON.
Happy coding.
*That is, for every property,
p
, in the source object(s), it merely doestarget[p] = source[p]
. Remember that, in JavaScript, Arrays are just a special subtype of object with a magicallength
: the value at index n is named by the property "n".从 jQuery 文档 http://api.jquery.com/jQuery.extend/ 中,它看起来 $.extend 只增加对象,而不增加数组。在示例中,您的
shat
变量从未更改过。From the jQuery document http://api.jquery.com/jQuery.extend/, it looks like $.extend only does Object augments, but not Array. In the example, your
shat
variable has never been changed.有趣的是,它确实有效,但不知道
extend
适用于数组。原因是这两个数组都包含对同一对象的引用。这与警告“新”的原因相同:
http://jsfiddle.net/yEnph/4/
两个变量都引用同一个对象,因此编辑对象会更新它们都引用的对象。
Interesting that that works at all, wasn't aware that
extend
worked on arrays.The reason for this though is that the two arrays both contain a reference to the same object. It's the same reason that this will alert "new":
http://jsfiddle.net/yEnph/4/
Both variables have a reference to the same object so editing the object updates the object, which they both reference.
如果获取了键,扩展只会覆盖属性:
因为数组只是具有数字属性名称的对象,所以您将用相同的原理替换它们,除了
"hello"
是"0"
, 等等。因为你有对象而不是基元,所以
shat
获取shot
的对象,它们被重写,因此原始shat
对象丢失。因此修改shot
的对象将会修改shat
的对象,因为它们是相同的对象。Extend just overwrites the properties if the keys are taken:
Because arrays are just objects with numeric property names, you will replace them with same principle except
"hello"
is"0"
, and so on.Because you have objects instead of primitives,
shat
getsshot
's objects, they are rewritten so the originalshat
objects are lost. So modifyingshot
's objects will modifyshat
's objects because they are the same objects.