3

I'm a beginner with Javascript and just need some clarification. I'm not really trying to achieve anything in particular here. Just a bit confused about this scenario.

When a variable assigned to an object is passed into a function as an argument, we can mutate the object permanently. However, we can't reassign it and make the changes stick. Why is that?

Here is some example code to what I mean:

Example1 - Mutation.

const house = {
  color1: 'white',
  color2: 'blue'
};

let paintIt = obj => {
  obj.color1 = 'gold'
};

paintIt(house);

house.color1 // Returns 'gold'

Example2 - Reassignment.

let house = {
  color1: 'white',
  color2: 'blue'
};

let paintItReassignment = obj => {
  obj = {
    forSale : false,
    includesGarden : true
  }
  console.log(obj) // Prints {'forSale':false, 'includesGarden':true}
};

paintItReassigment(house) // The reassignment does not work
house // Still returns {color1:'white', color2:'blue'}

house = {
 forSale : false,
 includesGarden : true
}; // Regular reassignment still works

Why does it stick when you modify the objects property (example1) but not when you reassign it (example2)?

logi666
  • 33
  • 4

1 Answers1

1

Unlike some other programming languages such as C, JavaScript uses a mixture of pass-by-reference and pass-by-value systems for its function calls. In a function, you can reassign the properties of an object passed to it, but you can't reassign the variable of the object itself. You can always do the following if you wish to reassign an object variable:

o = f(o);

To redefine multiple variables:

var {a,b} = f(a,b)

where, for instance:

function f(a,b){
    return {a:b,b:a};
}

Some discussion about this topic can be found here.

Chong Lip Phang
  • 8,755
  • 5
  • 65
  • 100
  • To be fair, it's exactly like passing a pointer as a parameter in C. If you assign to the pointer, you overwrite the reference, if you assign to a member of the pointer or the dereferenced value, you mutate the value. This concept of passing-reference-by-value absolutely does exist in C, just more explicitly than in JavaScript. – Patrick Roberts Sep 13 '20 at 01:05
  • Also your second example is illegal if either `a` or `b` has already been declared with `let` or `const`. – Patrick Roberts Sep 13 '20 at 01:08
  • I am not sure if the comparison is really fair. In C, we can reassign the variable by passing its pointer, can't we? const variables are not supposed to be changed. I guess a workaround to the second example is to pass in a 'unified' object, eg. f({a,b}). – Chong Lip Phang Sep 13 '20 at 01:14
  • It's unclear to me what you think is "unfair" about the comparison. By "variable" do you mean the reference or the underlying value? If you mean reference, then yes that's exactly what I was saying, and the pointer reference at the callsite of the function will not be modified by a direct assignment to the bare identifier within the body of the function definition. – Patrick Roberts Sep 13 '20 at 01:18
  • You've got the comparison the wrong way round. JavaScript always uses pass-by-value (even if they're reference values, i.e. pointers to objects). C, on the other hand, can choose to take an object by value or by reference, and what's more you can take references to variables and pass those around. – Bergi Sep 13 '20 at 01:41