2

有一个小测试。我希望这两个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"}})
4

4 回答 4

2

发生的事情change1obj最初持有对obj1.a. 但是,该行:

obj = {str: "change1"};

没有改变obj1.a。相反,它会创建一个新对象 ( {str: "change1"}) 并进行更改obj,以便它现在指向该对象而不是obj1.a.

相反,change2最初obj持有对 in 对象的引用obj2,并且具有以下行:

obj.a = {str: "change2"};

它访问被引用对象(即obj2)的内部结构,从而对该对象进行实际更改。

于 2013-09-27T09:46:09.257 回答
1

当您传递obj1.a到 时change1(),您发送的值obj1.a本身就是另一个对象。但是,当您发送obj2to时change2(),它会获取对象的引用,并且当您分配值时,原始值会发生变化,而在第一种情况下,这并没有发生。

正如所thg437建议的,这最好地解释了这种情况,

JavaScript 是按引用传递还是按值传递语言?

于 2013-09-27T09:46:20.697 回答
0

该语句 obj = {str: "change1"}; 导致obj引用传递的参数以外的其他内容,

其中obj.a = {str: "change2"}; 导致传递参数中的“a”属性更改为其他内容。

预计,在第一种情况下,您只是在更改输入的引用,而在其他情况下,您实际上是在修改输入参数。

于 2013-09-27T09:45:53.700 回答
0

来自MDN

函数调用的参数是函数的参数。参数按值传递给函数。如果函数更改了参数的值,则此更改不会在全局或调用函数中反映出来。但是,对象引用也是值,而且它们很特殊:如果函数更改了引用对象的属性,那么该更改在函数外部可见

在 change1 中,您正在传递obj.a,这实际上是一个值(因为它是对象引用,而不是对象本身)。这意味着您会收到该引用的副本,change1然后将其修改为指向新对象。您所做的只是修改传递给函数的引用副本,以便它有效地指向内存中的其他内容。

change2您传递objwhich 也是一个对象引用时,您正在修改该a引用的属性,因此您将获取引用指向的对象并修改其a属性。这个被修改的对象与您在函数中通过值接收的对象引用的副本和obj1代码顶部的引用所指向的对象相同。

于 2013-09-27T09:59:47.207 回答