Skip to content
loading...

JavaScript vs Java Pass by Value and Reference

Tiffany White on March 21, 2017

Different Languages, Different Paradigms When you are working with different languages at the same time, it is important to note that wh... [Read Full]
markdown guide
 

Both Java and Javascript are strictly pass-by-value. There is an important distinction to be made when talking about "passing a reference" versus "passing by reference."

Actual pass by reference semantics are illustrated here (using c#):

static void Main()
{
    int foo = 123;
    AddOne(ref foo); 
    Debug.Assert(foo == 124);
}

static void AddOne(ref int i) 
{
    i += 1;
}

As you can see, when passing by reference we are actually changing the value in-place, which is then reflected in the calling function. When passing an object by reference, it's even more apparent what's going on:

static void Main()
{
    Person p = new Person { Name = "William" };
    ChangePerson(ref p); 
    Debug.Assert(p.Name.Equals("Brian"));
}

static void ChangePerson(ref Person p) 
{
    p = new Person { Name = "Brian" };
}

Note that we didn't just alter a property of the Person passed to ChangePerson, we changed p to point to a different object altogether, which is once again reflected in the calling function. None of the above is possible in Java or Javascript, because they are strictly pass-by-value.

The special sauce to really understanding this is realizing that a reference is a value type. So, when you call a function and pass an object to it, you're actually passing a copy of a reference to that object. The copied reference still points to the same object in memory, but if you change where that reference points to in the callee, it doesn't affect the calling function because they are distinct references. Again, using a similar example from above:

static void Main()
{
    Person p = new Person { Name = "William" };
    ChangePerson(p);

    // Unlike the example above, this assertion fails!
    // We passed a *copy* of the reference to ChangePerson, not the reference itself!
    Debug.Assert(p.Name.Equals("Brian"));
}

static void ChangePerson(Person p) 
{
    p = new Person { Name = "Brian" };
}
 

Thanks for the explanation. Got it. Changed the article to reflect that.

 

Shouldn't

const a;
const b = 8;

const b = a;

console.log(a); // will return 8

not print 8?

 

I should have probably used let in this example. Good catch.

 

Sorry but even with let, I don't think it works... Are you sure?

Yeah, I updated it to use var, at least for now.

 

It's interesting in Javascript.
Learn JavaScript here: hackr.io/tutorials/learn-javascript

Consider this example:

function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);
console.log(obj1.item);

console.log(obj2.item);
Run code snippetExpand snippet
This produces the output:

10
changed
unchanged

If it was pure pass by value, then changing obj1.item would have no effect on the obj1 outside of the function. If it was pure pass by reference, then everything would have changed. num would be 100, and obj2.item would read "changed".

Instead, the situation is that the item passed in is passed by value. But the item that is passed by value is itself a reference. Technically, this is called call-by-sharing.

In practical terms, this means that if you change the parameter itself (as with num and obj2), that won't affect the item that was fed into the parameter. But if you change the INTERNALS of the parameter, that will propagate back up (as with obj1).

 

Thanks for writing this post. In studying and using JS for years, I only just found out about this concept today. :mindblown:

code of conduct - report abuse