user4501874
user4501874

Reputation:

Pass-by-reference JavaScript objects

Please read the comments in the code below to know what I am trying to ask.

Expected Output: As per pass-by-reference mechanism in JavaScript, objOne is expected to log {} at the end, because objTwo was initialized with {}.

var objOne = {
  x: 1,
  y: 2
};

var objTwo = objOne;

// change the x vlaue to 2 by objTwo
objTwo.x = 2;

// Change the value of key x in objOne as well - pass by reference mechanism
console.log(objOne); // { x: 2, y: 2 }

/*** Pass by reference is understood in code, above this comment ***/

// Now what if objTwo initialized with empty object
objTwo = {};

console.log(objOne); // { x: 2, y: 2 } but expected output = {}

// As per pass by reference mechanism. objOne is expected to log {}, because objTwo was initialized with {}.

Upvotes: 31

Views: 32845

Answers (9)

trincot
trincot

Reputation: 350137

As per pass-by-reference mechanism in JavaScript

Let's get this out of the way: there is no pass-by-reference mechanism in JavaScript. Pass-by-reference is a very specific feature. To know whether a language supports it, you should check whether it is possible to pass a variable with an immutable value to a function (for instance an integer), and after that call see that this variable has a different immutable value. If this is not possible, then the language does not support pass-by-reference. JavaScript does not support it. C does not support it. C++ does support it (by declaring a function parameter with &).

As to your code example; let's visualise it.

First phase

After the first two var statements we get this:

objOne
  ↓  
┌───────────┐
│ x: 1      │
│ y: 2      │
└───────────┘
  ↑  
objTwo

Only one object was created (using object literal syntax).

After objTwo.x = 2, we get:

objOne
  ↓  
┌───────────┐
│ x: 2      │
│ y: 2      │
└───────────┘
  ↑  
objTwo

Only one property value was changed, in the only object that was created. Whether you look at the object via variable objOne or objTwo does not make a difference.

Second phase

objTwo = {} creates a second object and assigns its reference to objTwo. Now we have two, distinct objects:

objOne
  ↓  
┌───────────┐
│ x: 2      │
│ y: 2      │
└───────────┘

objTwo
  ↓  
┌───────────┐
└───────────┘

You cannot change which object objOne is referencing without making an assignment to objOne. Even though objOne and objTwo first referenced the same object, these variables are still distinct references. In the first phase we saw we can mutate the object that objOne references, but it is still the same object -- just one that was subject to some mutation. It is not possible to make objOne reference another object by making an assignment to objTwo. You really need to assign to objOne to make that happen.

Conclusion

There is no pass-by-reference mechanism in JavaScript. In JavaScript objects are accessed and manipulated through references. objTwo is not an alias for objOne, it only is a duplicate reference for the same object. As soon as another reference is assigned to objTwo, we have two distinct references.

Upvotes: 1

Uddesh Jain
Uddesh Jain

Reputation: 1104

This is how pass-by-reference works. Here objTwo is referring to objOne so whatever you do with objTwo will also happen with objOne.

Upvotes: 0

Mihajlo Supic
Mihajlo Supic

Reputation: 65

I agree with accepted answer, this is just some code to back it up.

let objOne = {x: 1, y: 2};
let objTwo = objOne; // referencing to same thing

objTwo.x = 2;
console.log(objOne, objTwo); // output {x:2, y:2}, {x:2, y:2}

let objThree = {};
objTwo = objThree; // notice this. Same as "objTwo = {}", except now you have objThree as initial reference
console.log(objOne, objTwo, objThree); // output {x:2, y:2}, {}, {}

You can easily notice what happened by changing objTwo reference or adding it complete new value as it was shown in question example.

Upvotes: 4

Shadi Shaaban
Shadi Shaaban

Reputation: 1720

JavaScript pass by reference is different, your object is treated as a reference as long as you're changing its attributes like obj.x = 1, but assignment of the object variable itself (obj = []) will treat it as value-based variable.

Upvotes: 1

Jack jdeoel
Jack jdeoel

Reputation: 4584

only delete can call initialize state ..

for(var i in objOne){
    delete objOne[i];
}

@nrabinowitz saying

  • Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
  • Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.
  • However, changing a property of an object referenced by a variable does change the underlying object.

Upvotes: 1

deceze
deceze

Reputation: 522016

When you assign one variable to another, it's not that both those variables are now linked by reference; you're misunderstanding what "pass by reference" means here.

A variable holding an object does not "directly" hold an object. What it holds is a reference to an object. When you assign that reference from one variable to another, you're making a copy of that reference. Now both variables hold a reference to an object. Modifying the object through that reference changes it for both variables holding a reference to that object.

When you assign a new value to one of the variables, you're just modifying the value that variable holds. The variable now ceases to hold a reference to the object, and instead holds something else. The other variable still holds its reference to the original object, the assignment didn't influence it at all.

Upvotes: 53

haim770
haim770

Reputation: 49095

When 2 variables are pointing to same object, it doesn't mean that they're now magically 'tied' to each other.

In your case, objTwo = {} is simply changing objTwo to point at the new object you created.

Upvotes: 7

Joseph
Joseph

Reputation: 119837

objTwo = {}; doesn't work the way you think it works. I usually recommend thinking of variables as "pointers".

objOne and objTwo are two totally different variables. When you did objTwo = {};, what it did was have the objTwo variable point to another object. It does not alter the objOne variable.

Let's visualize:

var objOne = {
  x: 1,
  y: 2
};

// objOne -> { x: 1, y: 2 }

var objTwo = objOne;

// objOne -> { x: 1, y: 2 } <- objTwo

objTwo.x = 2;

// objOne -> { x: 2, y: 2 } <- objTwo (update object via objTwo variable)

objTwo = {};

// objOne -> { x: 2, y: 2 }, objTwo -> {}

Upvotes: 5

Razzi Abuissa
Razzi Abuissa

Reputation: 4092

When you evaluate

objTwo = {};

Javascript interprets that as reassigning objTwo to a new literal empty object, and leaves its old value alone.

If you want to remove a key from objOne by reference, you can use the delete keyword:

delete objTwo.x;  // also deletes the x property of objOne

Upvotes: 14

Related Questions