2

There's a small test. I expect both obj\d object have their a menmber changed in the end. However the change1 style doesn't work, I wonder why, or why not, should it behave like this?

<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>

Result(after you click the button):

obj1: ({a:{strblahblah:"blah"}})
obj2: ({a:{str:"change2"}})
Byzod
  • 466
  • 4
  • 18

4 Answers4

2

What's happening in change1 is that obj initially holds a reference to the object in obj1.a. However, the line:

obj = {str: "change1"};

doesn't change obj1.a. Instead it creates a new object ({str: "change1"}) and changes obj so that it now points to this object instead of obj1.a.

In contrast, change2 has obj initially holding a reference to the object in obj2, and has the line:

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

which accesses the internal structure of the referenced object (i.e. obj2) and hence makes actual changes to that object.

Ben Jackson
  • 11,722
  • 6
  • 32
  • 42
  • Uhh, reference, now I can understand it better, but, is there any way to do things like `change1`? Because I want to modify the `a` of `obj\d` but I don't want to expose `obj\d` itself to the `change` method – Byzod Sep 27 '13 at 15:32
  • I think maybe you want something like this: http://stackoverflow.com/questions/8421605/how-to-set-a-specific-property-on-a-private-object – Ben Jackson Sep 27 '13 at 19:57
1

When you pass obj1.a to change1(), you are sending the value of obj1.a which itself is another object. But when you send the obj2 to change2(), its taking the reference of the object, and when you assigned the value the original value got changes, where as in the first case this had not happened.

As thg437 suggested, this best explains the case,

Is JavaScript a pass-by-reference or pass-by-value language?

Community
  • 1
  • 1
Ashis Kumar
  • 6,494
  • 2
  • 21
  • 36
0

This statement obj = {str: "change1"}; causing obj to refer to something other than the passed argument,

where as obj.a = {str: "change2"}; causing "a" property in passed argument to be changed to something else.

It is expected, in 1st case you're just changing reference of input and in other case you're actually modifying input parameter.

999k
  • 6,257
  • 2
  • 29
  • 32
Piyuesh
  • 1,066
  • 1
  • 9
  • 18
0

From MDN:

The parameters of a function call are the function's arguments. Arguments are passed to functions by value. If the function changes the value of an argument, this change is not reflected globally or in the calling function. However, object references are values, too, and they are special: if the function changes the referred object's properties, that change is visible outside the function

In change1 you are passing obj.a, which is actually a value (because it is an object reference, not the object itself). This means that you receive a copy of that reference in change1 and then modify it to point to a new object. All you've done is modify the copy of the reference that was passed into the function so that it's effectively pointing to something else in memory.

In change2 you are passing obj which is an object reference as well, but you are then modifying the a property of that reference, so you're getting the object that's pointed to by the reference and modifying its a property. This object that is modified is the same one that is pointed to by both the copy of the object reference you received by value in the function and the reference obj1 at the top of the code.

Neil Mountford
  • 1,951
  • 3
  • 21
  • 31