7

Quick question on Javascript to which I can't find a clear concise answer.

I'm building an app that's way ahead of anything I've done before and involves multiple classes being instantiated. These objects are then passed into a processing class that checks user inputs, draws onto canvas and updates the objects that it has been passed.

I am wondering, how does JavaScript handle passing objects to functions? Am I passing a copy of the object, or am I passing a reference to the object?

So if my controller class alters one of the objects variables, is that changed everywhere or just in the object that that controller sees?

Sorry for such a simple, possibly easily testable question but I'm not even sure if I'm making a class correctly at this point thanks to errors piling up.

SCGH
  • 887
  • 8
  • 13
Chris Morris
  • 943
  • 2
  • 17
  • 41
  • http://www.google.com/search?q=javascript+call-by-reference+vs+call-by-value – CBroe Jun 28 '13 at 08:55
  • You're passing a reference. Assignments `obj1 = obj2` also just create more references to the same object. – nnnnnn Jun 28 '13 at 08:56
  • in javascript objects are passed by reference –  Jun 28 '13 at 08:57
  • 1
    Did you see [this answer?](http://stackoverflow.com/a/5314911/978264) I see your pain as the answers are ambiguous but this cleared things up for me. Best bet is to do a bit of experimenting with jsFiddle for clarity :-) – Stokedout Jun 28 '13 at 09:02
  • Thanks for the link, I'm not too sure of the syntax but it does illustrate the way i;ve been doing it in the second part and nice to know it is being done correctly. 200 lines of code and 4 hours last night weren't wasted. – Chris Morris Jun 28 '13 at 09:08
  • This explains it all: http://stackoverflow.com/questions/13506398/why-are-objects-values-captured-inside-a-self-executing-function/13508654#13508654 – slebetman Jun 28 '13 at 09:10
  • Interesting. hazzik's deleted answer is actually correct but without further explanation most javascript programmers will think it's wrong. See my link above to see what's really going on and why I say hazzik was right. – slebetman Jun 28 '13 at 09:16
  • @slebetman: this question is perhaps the weirdest one here on SO. It has thousands of answers, _all_ of them are wrong. Amazing! – georg Jun 28 '13 at 09:39
  • @slebetman - Hazzik's deleted answer is backwards. All function arguments in JS are passed by _value,_ but for objects the value is a reference to the object. Which is kind of what your linked answer says, except it uses weird terminology for it: "by copy of reference"? Yes, that's by value. – nnnnnn Jun 28 '13 at 10:43
  • @nnnnnn: Actually, for primitive types the thing it passes is also a reference. Think about it - it also works out to have the same behavior as what is currently observed. To wit: in javascript everything is passed by value to a reference. For everything. There is no need to differentiate between objects and numbers and strings once you understand this. – slebetman Jun 28 '13 at 11:29
  • @slebetman - I have thought about it, and I think that it is a much more confusing way to describe the behaviour, especially when the terms "pass by value" and "pass by reference" are commonly used in several other programming languages to mean the same thing I'm describing but the opposite of the way you are trying to use them. (Differentiating between objects and primitives doesn't bother me at all - it's really not very complicated.) – nnnnnn Jun 28 '13 at 11:40

3 Answers3

3

When passing in a primitive type variable like a string or a number, the value is passed in by value. This means that any changes to that variable while in the function are completely separate from anything that happens outside the function.

function myfunction(x)
{
      // x is equal to 4
      x = 5;
      // x is now equal to 5
}

var x = 4;
alert(x); // x is equal to 4
myfunction(x); 
alert(x); // x is still equal to 4

Passing in an object, however, passes it in by reference. In this case, any property of that object is accessible within the function

function myobject()
{
    this.value = 5;
}
var o = new myobject();
alert(o.value); // o.value = 5
function objectchanger(fnc)
{
    fnc.value = 6;
}
objectchanger(o);
alert(o.value); // o.value is now equal to 6
painotpi
  • 6,894
  • 1
  • 37
  • 70
  • 1
    Actually that's not 100% accurate, it *looks like* a pass by reference, sometimes it also behave as it, but in javascript variables are passed by reference. For objects and arrays, the value passed is a reference to the object, but that's slightly different than saying it's passed by reference. Passing the object reference is different than passing the object itself. Sorry for the punctuation :) – Lorenzo Marcon Jun 28 '13 at 10:05
  • 2
    _"but in javascript variables are passed by reference"_ - @lorenzo.marcon - in JS it's the opposite. Everything is passed by value, but with objects the value is a reference to the object. It's not like "by reference" in some other languages where a function can change the variable that was passed in. EDIT: Actually I just noticed that you said as much in your answer, so I assume this was just a typo in your comment. – nnnnnn Jun 28 '13 at 10:39
  • 1
    ehrm.. my bad, it's a typo. Obviously I meant by value! ALWAYS by value in JS. that's what I also wrote on my answer, before writing the comment. but thanks for pointing it out! I wonder if someone could correct it, since I cannot edit it anymore. – Lorenzo Marcon Jun 28 '13 at 10:42
3

As well described in https://stackoverflow.com/a/5314911/636348, in JavaScript it's always pass by value, but for objects the value of the variable is a reference.

So, it's not a pure pass by reference. Here's an example to understand this concept:

E.g.:

x = {member:"foo"}

If you change the object with another object inside a function, you won't get the new object outside the function scope because you just create another object. The original reference is still bound to the original object:

function changeObject(x) {
  x = {member:"bar"};
}

changeObject(x);
alert(x.member)

output: foo

instead, if you alter a member inside a function, the object will be changed:

function changeMember(x) {
  x.member = "bar";
}

changeMember(x);
alert(x.member)

output: bar

Community
  • 1
  • 1
Lorenzo Marcon
  • 8,029
  • 5
  • 38
  • 63
  • Do we have a reason for why this happens? Also, Is this termed as some particular phenomenon in Javascript? – Chirag Mongia Jul 18 '17 at 11:37
  • I'd say that it is a mix of understanding _scope_ and _passing objects' reference_. Further info here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects – Lorenzo Marcon Jul 18 '17 at 12:37
1

If you pass in a variable which is pointing to an object, it passes a reference to the object. If you pass in an object literal, then obviously no other class or function will be able to change that object.

Racheet
  • 730
  • 8
  • 21
  • I beg to differ about your second sentence - the function could well save additional references to the object in question and make them available to other code outside the function. Whether an object was originally created via a literal is irrelevant. – nnnnnn Jun 28 '13 at 08:58
  • Right Ok Thank you for the info, though I'm not sure what a object literal is. My experience with classes is lacking outside of a MVC Framework and moreso outside of javascript – Chris Morris Jun 28 '13 at 09:04
  • @nnnnnn You're right of course, for some reason I hadn't taken into account the idea that the function might leak one of its parameters into global state. That'll teach me to fire off 20 second responses on SO. – Racheet Jun 28 '13 at 13:46
  • @ChrisMorris What I was basically trying to say was that if you create an object as part of the function call then obviously you aren't passing a reference to an object that exists and was previously accessible from anywhere else. nnnnnn pointed out that actually the function could take that object and the store a reference to it in a global variable, or pass it off to some other function, and then a reference to that object would be accessible from somewhere else. – Racheet Jun 28 '13 at 13:48