DEV Community

JavaScript vs Java Pass by Value and Reference

tiff 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...
Collapse
 
dubyabrian profile image
W. Brian Gourlie

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;
}
Enter fullscreen mode Exit fullscreen mode

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" };
}
Enter fullscreen mode Exit fullscreen mode

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" };
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
tiffany profile image
tiff

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

Collapse
 
niharmore33 profile image
nihar

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

Collapse
 
tiffany profile image
tiff

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

Collapse
 
yigaldviri profile image
yigaldviri

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

Thread Thread
 
tiffany profile image
tiff

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

Collapse
 
jenc profile image
Jen Chan

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