5

I understand the following property of the javascript language:

var bar = 1;
var foo = bar;
bar = "something entirely different";
// foo is still 1

However, when trying to apply this logic to an object it seems to act differently:

var bar = {};
bar.prop = 1;
var foo = bar;
bar.prop = "something entirely different";
// foo.prop now changes to "something entirely different"
// but...
bar = "no longer an object";
// now foo remains an object with the prop property

Can someone tell me what's happening and why there is a difference?

Jeff
  • 556
  • 4
  • 9
  • 3
    I may have answered my own question: "Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object." But this is still confusing, can someone explain more? – Jeff Feb 27 '12 at 22:50
  • See my answer Jeff, please let me know if that makes any sense? – Josh Feb 27 '12 at 22:52
  • possible duplicate of [Is Java pass by reference?](http://stackoverflow.com/questions/40480/is-java-pass-by-reference) – Mike Samuel Feb 27 '12 at 22:57
  • That question is relevant because nothing about your question is JavaScript specific. – Mike Samuel Feb 27 '12 at 22:57
  • 1
    @MikeSamuel You can't perform the above code snippets in Java, you will get an error. I would say the use of JavaScript code in reference to what was confusing him would make this question about JavaScript. – Brandon Buck Feb 27 '12 at 22:59

3 Answers3

1

That's correct. When you assign a variable to an object, you're really creating a second reference to that object. In the first case, what you're doing is assigning bar to point at the string foo points to, but then you change what bar points to when you reassign bar.

In the second example, you assign bar to a new object, then you point foo at that same object, then you reassign bar to a string. foo is still pointed at the same object.

Think of it like this: bar = "something" is changing what bar points to, not changing the actual object {} to a string.

This article is a fairly good explanation of what you're seeing. I'm looking for even better / more authoritative references, however.

Josh
  • 10,961
  • 11
  • 65
  • 108
  • 1
    This is what I was going to say, the memory containing the object `bar` was assigned to is not erased and replaced with `"no longer an object"` but the reference is dropped (and if it had not other references it would be queued for garbage collection). – Brandon Buck Feb 27 '12 at 22:54
1

Let's take it line by line:

var foo = bar;

All that names of objects do is hold addresses in memory. So in this statement, you are making foo hold the same memory address as bar. If for example bar was holding 0xFF, then via the assignment you would make foo also hold 0xFF.

However, keep in mind that bar and foo are two distinct objects, they happen to just hold the same address in memory.

Now, since they do happen to hold the same address in memory, mutating members of bar will also affect the members of foo because they are bound to the same object.

bar.prop = "something entirely different";  // affects foo.prop also

However, here is the key point to remember:

Assignment only changes what the name of the object is bound to, and does not affect any other objects.

In other words, the statement below made bar hold a different memory address, but this does not affect foo.

bar = "no longer an object"; // Made bar hold a different memory address

Now, explaining the quote:

Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.

Take this example:

function f(obj1, obj2)
{
    obj1.prop = 10;
    obj2 = {prop: 20};
}

var bar = {prop: 1};
var foo = {prop: 2};
f(bar, foo);
console.log("bar.prop: " + bar.prop + ", foo.prop: " + foo.prop);

This prints outs: bar.prop: 10, foo.prop: 2. Inside function f, obj1 holds the same memory address as bar and obj2 holds the same memory address as foo. However, only bar is affected because inside f only altering members of objects are reflected and assignment obj2 = {prop: 20}; only affects the local variable obj2 not foo.

In other words, the "value" is a reference to an object means, altering members affects the referenced object but assigning only affects the local variable.

Jesse Good
  • 50,901
  • 14
  • 124
  • 166
  • I think that is the most confusing explanation I've seen. Forget all about memory and addresses, ECMA-262 specifies behaviour, not implementation. – RobG Feb 28 '12 at 00:18
  • @RobG: I think concrete rather than the abstract makes more sense to me (which was what I was trying to do), but thanks for the comment (I realize this way may not be appropriate for everyone). However, more *specific* comments would be more beneficial for me. – Jesse Good Feb 28 '12 at 01:02
0

In the first code you define the Var bar as variable.

in the second code you define it as an object.

The variables take a place in the memory;so when you define foo from bar its will be the same type as variable and will reserve a new memory location; and when you use equal operator you are replacing the data content of this variable.

The object in the second sample code on initialize will point (as pointer) to a memory location that will contain the data of this object; and when you define foo from bar its will be the same type as object and will point to the same memory location; so changing one of these two reference object value will reflect on the other one.

Mohammad Shraim
  • 1,173
  • 12
  • 21