DEV Community

tiff
tiff

Posted on

JavaScript vs Java Pass by Value and Reference

Different Languages, Different Paradigms

When you are working with different languages at the same time, it is important to note that while most languages are based on C, each langauge has its own set of rules and paradigms associated with it that makes similar conventions different.

Java and JavaScript, while having Java in common, are completely different languages1. As such, the way they deal with primitive values2, functions and methods, arguments and parameters, differ as well.

Dealing With Objects and Methods in Java

Java is an Object Oriented Programming language which basically means creating objects as part of a class, instantiating the object and adding methods to the object to actually do things with the newly created objects. You can then make your code more modular by adding and calling functions that manipulate the code in some way.3

You can create an object such as:

  public class Dog {
      int dogAge;
      public Dog(string name) {
      System.out.println("My dog's name is " + name " .");
   }

   public void setAge (int age) {
       dogAge = age;
    }

   public int getAge() {
       System.out.println("My dog is " + dogAge + " years old");
       return dogAge;
     }

     public static void main (String []args) {
     /* Create an object using the new keyword */
         Dog myDog = new Dog("Max");
         myDog.setAge(11); // setAge is a class method on the object Dog
         myDog.getAge();
         System.out.println(myDog.dogAge);
       }
    }

Here we have a class and a new object Dog with a few getter and setter methods on the Dog object.

This is standard Java OOP stuff. JavaScript isn't an OOP language, it is a prototypal language which creates object prototypes in order to extend objects through prototypal inheritance instead of classical inheritance, like Java.4

Dealing with Objects and Methods in JavaScript

Objects in JavaScript are not created the same way as in Java. At least not technically, and this:

    function Car() {
     const car1 = new Car();
    }

should be avoided.5

We can create an object literal such as:

    const myObject {
        foo: 'bar',
        car: 'Mazda',
        age: 38
    }

and add methods onto the object such as:

    myObject.car = 'Honda';

and pass them to other methods like console.log:

    console.log(myObject.car);

Pass by Value in JavaScript

The only thing you can pass by value in JavaScript are primitive data types.

Passing by value means that you have two variables in memory that are assigned to one another. For instance:

    var a;
    var b = 8;

    var a = b;

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

What's happening when we pass these primitives by value, we are making a copy of the value of the variable b stored in memory, say at address 0x001 and assigning it to a stored at 0x002. Both a and b mirror each other as they are just copies of one another. This is what is meant when we say we are passing by value in JavaScript.

Pass by Value in Java

Take this bit of code:

    int y = 10;
    changeMeToSix (y);
    System.out.println(y);
    // [...some code]

    void changeMeToSix (int x) {
        x = 6;
    }

This doesn't print 6. It prints 10. Why? Because only the value 10 was passed into the method, not the variable itself.

Another example:

    Dog myDog;

This is not actually a dog but a pointer to the Dog instance in memory. So if we have:

    public void foo (Dog yourDog) {
        yourDog.setName("Sparky");
        yourDog = new Dog("Max");
        yourDog.setName("Jeffie");
    }

Let's say the parameter yourDog is at memory address 0x001.

The first line is followed to the Dog it points to, which is the Dog object at 0x001. That dog is asked to change names to Sparky, at the same address of 0x001.

In the second line, a new Dog is created at a different address, say, 0x006. We assign the yourDog param to the memory address 0x006.

In the last line, yourDog is followed to the new Dog it points to in 0x006. That Dog changes his name to Jeffie. Then it returns.

myDog didn't change. myDog is a pointer in memory that points to the original address, 0x001, not an actual Dog.

You can pass references to parameters by value and not the actual references themselves.

Pass by Reference JavaScript

Passing by reference in JavaScript can only happen to objects. This includes functions as functions are first-class objects in JavaScript.6

Passing by reference involves having two references point to the same object in memory. This means you can mutate and object or function by assigning it to another object or passing it as a parameter to a function. Take this code:

    // by reference (all objects (including functions))
   const greet = {
      greeting: 'hi' 
    };
   const greet1;

  greet1 = greet;
  greet.greeting = 'hello'; // mutates to hello

  console.log(greet);
  console.log(greet1);

  // by reference (even as parameters)
  function changeGreeting(obj) {
    obj.greeting = 'What's up?'; // mutates to What's Up  
  }

 changeGreeting(greet1);
console.log(greet);
console.log(greet1);

// equals operator sets up new memory address
greet = { 
    greeting: 'Yo' 
};
console.log(greet); // Mutates to Yo
console.log(greet1);

...and so on.

Understanding the difference between pass by value and pass by reference is key to understanding how JavaScript objects and primitives work.

Pass by Reference in Java?

You cannot pass by reference in Java. As Jon Skeet puts it:

Pass by reference mixes inputs and outputs of code. This is the fundamental problem with the technique. In Java, a programmer can assume that variables will not change their value when passed as parameters to a method. In languages with pass by reference semantics, this basic assumption cannot be made.

Pass by reference confuses the interface to a method. Methods written using pass-by-reference semantics can have extremely complex interfaces that are difficult for client programmers to learn and understand.

Excluding pass by reference was a design choice. It fills a need in some languages, like JavaScript but can present problems in others.

That Was Long

Sorry about the length! If you have anything to add, leave a comment down below. Let me know if I am wrong or off-base. I don't mind.

UPDATE: I suppose you can't redeclare a variable with let in the example of pass by value in JS. So I went to the console, did some console-fu and decided to use var though it is dated. Still learning ES6.

UPDATE 2: So I learned you cannot pass by reference in JavaScript though that is exactly what I was taught, albeit incorrectly. You can pass a reference to another object, but you cannot pass by reference in JavaScript.

This post was originally posted on my blog Just Another DevBlog


  1. Both languages are based on C, however. 

  2. Both Java and JavaScript have primitive types. Java has strongly typed primitive values. See this post for Java data types. 

  3. Technically, in Java, you can use method and function interchangeably but I really don't like doing that. See this answer

  4. Eric Elliott has talked about this a lot. Check it out for the differences inheritance between the two languages. 

  5. This is creating an object using a JavaScript constructor and the new keyword, mimicking OOP inheritance in JavaScript. Douglas Crockford recommends that you avoid it. 

  6. More in another post. 

Top comments (7)

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: