有一个小测试。我希望两个obj\d
对象最终都会更改a
个更改。然而,change1
样式不起作用,我想知道为什么,或者为什么不这样,它应该像这样?
<button id="btn1" onclick="test()">Change</button>
<script>
var obj1 = { a : {strblahblah: "blah"} };
var obj2 = { a : {strblahblah: "blah"} };
function test(){
change1(obj1.a);
change2(obj2);
alert("obj1: " + obj1.toSource() + "\r\nobj2: " + obj2.toSource());
}
function change1(obj){
obj = {str: "change1"};
}
function change2(obj){
obj.a = {str: "change2"};
}
</script>
结果(单击按钮后):
obj1: ({a:{strblahblah:"blah"}})
obj2: ({a:{str:"change2"}})
答案 0 :(得分:2)
change1
中发生的事情是obj
最初持有对obj1.a
中对象的引用。但是,行:
obj = {str: "change1"};
不会更改obj1.a
。相反,它会创建一个新对象({str: "change1"}
)并更改obj
,以便它现在指向此对象而不是obj1.a
。
相比之下,change2
obj
最初拥有对obj2
中对象的引用,并且有一行:
obj.a = {str: "change2"};
访问引用对象的内部结构(即obj2
),从而对该对象进行实际更改。
答案 1 :(得分:1)
当您将obj1.a
传递给change1()
时,您发送的值obj1.a
本身就是另一个对象。但是当您将obj2
发送到change2()
时,它会引用该对象,并且当您分配该值时,原始值会发生变化,而在第一种情况下,这种情况并未发生。
正如thg437
建议的那样,这最好地解释了这个案例,
Is JavaScript a pass-by-reference or pass-by-value language?
答案 2 :(得分:0)
此声明obj = {str: "change1"};
导致obj
引用除传递的参数之外的其他内容,
其中obj.a = {str: "change2"};
导致传递参数中的“a”属性被更改为其他内容。
预计,在第一种情况下,您只是更改输入的参考,而在其他情况下,您实际上正在修改输入参数。
答案 3 :(得分:0)
来自MDN:
函数调用的参数是函数的参数。 参数按值传递给函数。如果功能改变了 参数的值,这种变化不会全局或反映 调用功能。但是,对象引用也是值,和 它们很特别:如果函数改变了引用的对象 属性,该变化在函数外可见
在change1中,您传递obj.a
,这实际上是一个值(因为它是对象引用,而不是对象本身)。这意味着您在change1
中收到该引用的副本,然后将其修改为指向新对象。您所做的就是修改传递给函数的引用副本,以便它有效地指向内存中的其他内容。
在change2
中,您传递obj
也是一个对象引用,但是您正在修改该引用的a
属性,因此您将获得指向的对象通过引用并修改其a
属性。修改的此对象与函数中的值和代码顶部的引用obj1
所接收的对象引用的副本所指向的对象相同。