57

i have a object, which is getting passed in many different functions inside a function. these functions may or may not change the value of the object, but if they do change it, then i would like to get the latest changes on object.

following is what im trying to do:

var ob = {text: 'this is me', name: 'john'}

function (object) {

     changeObject(object);
     customObjectChanger(object);
     callback = function (object) {
          object.text = 'new text';
     }

     callback(object);

     // object value here should be object{text: 'new text', name: 'john'};    
}
Basit
  • 16,316
  • 31
  • 93
  • 154
  • 2
    Javascript automatically passes objects by reference all the time. Have you tried your above code to see if it already does what you want? – jcsanyi Jun 02 '13 at 06:40
  • no, i haven't. i did read it. just wanted to confirm here. – Basit Jun 02 '13 at 06:41
  • 3
    JavaScript does *not* [Pass By Reference](http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference). However, JavaScript *does not make copies of objects when they are passed or assigned*. As such, it is the *same* object with a different name - changes made to the object (from any name) affect said object. – user2246674 Jun 02 '13 at 06:43
  • 3
    It depends on what you mean by "pass by reference". In my view, "the same object with a different name" is the very definition of reference. – jcsanyi Jun 02 '13 at 06:45
  • @jcsanyi This is why defining terms and avoiding ambiguity is important. (The Wikipedia article does admit that the term is ambiguous which is why I try to *avoid* using "Pass By Reference", except in cases where in unequivocally means that changing the local name binding affects the caller.) – user2246674 Jun 02 '13 at 06:47

5 Answers5

173

In JavaScript objects are always passed by copy-reference. I'm not sure if that's the exactly correct terminology, but a copy of the reference to the object will be passed in.

This means that any changes made to the object will be visible to you after the function is done executing.

Code:

var obj = {
  a: "hello"
};

function modify(o) {
  o.a += " world";
}

modify(obj);
console.log(obj.a); //prints "hello world"

Having said that, since it's only a copy of the reference that's passed in, if you re-assign the object inside of your function, this will not be visible outside of the function since it was only a copy of the reference you changed.

Code:

var obj = {
  a: "hello"
};

function modify(o) {
  o = {
    a: "hello world"
  };
}

modify(obj);
console.log(obj.a); //prints just "hello"
Huy-Anh Hoang
  • 777
  • 6
  • 24
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • 2
    http://en.wikipedia.org/wiki/Evaluation_strategy - I prefer "Call By [Object] Sharing" for it's directness, separation of implementation concerns, and reduced ambiguity with other call conventions. ECMAScript does *not* use "Reference" for this purpose in any part of the specification. (The Reference Specification Type does not apply to function calls.) – user2246674 Jun 02 '13 at 06:46
  • 4
    +1 for a clear description of what's different from a traditional pass-by-reference. – jcsanyi Jun 02 '13 at 06:50
  • @user - interesting - thanks for the info. One of these days I'll get around to actually reading the spec :) – Adam Rackis Jun 02 '13 at 06:52
  • In JavaScript, "objects" cannot be "passed" because objects are not values. – newacct Jun 03 '13 at 08:50
  • 2
    I think I made clear that a copy of the reference to the object is passed, and not the object itself. – Adam Rackis Jun 03 '13 at 13:56
  • This might not be clear for everyone - this also works the same when accessing object properties through `[]` operator like `obj[prop]` - very helpful when e.g. initializing some default settings by extra function - I've created a little fiddle to demonstrate that: http://jsfiddle.net/s3n2n4y7/ – jave.web Jul 11 '15 at 07:58
  • In your example, inside the function, instead of o={a:"hello world"}, if you put o.a ="hello world", you'll change your object, and obj.a will alert "hello world" – Porkopek Jan 15 '17 at 16:53
  • So long this was created, and the 'copy reference' term is so noisy because of its redundancy, yet no one has pointed out the inconsistencies. It would be better to name it a 'soft reference'. A reference is just a pointer or a descriptor. A copy of the reference would be a value with exactly the same functionality of the original reference. It is a nice effort to name the concept but not right. Adding the adjective or characteristic 'soft' or 'hard' allows to treat the reference differently. Just like File Links. A soft reference is replaced on assignment and a hard one replaces the object. – Melo Waste Jan 05 '18 at 21:18
  • 6
    How can I handle this problem? What if I want to change the object itself rather than its copy reference? – abhinav1602 Mar 08 '18 at 07:08
  • @Abhinav1602 Did you get an answer to your question – Dibzmania May 17 '19 at 04:14
  • @Dibzmania I think I asked the wrong questions here last year. Let me know what you want to achieve n maybe I can help you with that if you are looking for any answer. – abhinav1602 May 18 '19 at 06:03
  • 1
    @Abhinav1602 I wanted to reassign an object within a function and it's new value be visible in the calling function. – Dibzmania May 18 '19 at 14:58
  • 1
    To update the object itself, you can `Object.assign(o, newObject);` – 8ctopus Oct 08 '21 at 06:15
7

"Objects" are not values in JavaScript, and cannot be "passed".

All the values that you are dealing with are references (pointers to objects).

Passing or assigning a reference gives another reference that points to the same object. Of course you can modify the same object through that other reference.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • 3
    Indeed - so a copy of the reference to the object is ..."passed" -_- – Adam Rackis Jun 03 '13 at 13:53
  • Indeed the object will not be passed, but a reference will, and you can modify its properties if you alter them inside of the receiver function – Ignacio Jul 15 '15 at 21:25
  • Simple, concise answer. When an object is assigned to a variable, the value assigned is a reference to the object. So all variables hold a value, but some values are references to objects (e.g. object, function, array) and some are literals (e.g. number, string, boolean and other primitives). – RobG Mar 29 '20 at 01:12
6

This is more explanation for Pass by value and Pass by reference (Javascript). In this concept, they are talking about passing the variable by reference and passing the variable by reference.

Pass by value (Primitive Type)

var a = 3;
var b = a;

console.log(a); // a = 3
console.log(b); // b = 3

a=4;
console.log(a); // a = 4
console.log(b); // b = 3
  • applies to all primitive type in JS(string, number, boolean, undefined, null).
  • a is allocated a memory (say 0x001) and b creates a copy of the value in memory (say 0x002).
  • So changing the value of a variable doesn't affect the other, as they both resides in two different locations.

Pass by reference (objects)

var c = { "name" : "john" };    
var d = c;

console.log(c); // { "name" : "john" }
console.log(d); // { "name" : "john" }

c.name = "doe"; 

console.log(c); // { "name" : "doe" }    
console.log(d); // { "name" : "doe" }
  • JS engine assigns the object to the variable c, it points to some memory say (0x012)
  • when d=c, in this step d points to the same location (0x012).
  • changing the value of any changes value for both the variable.
  • functions are objects

Special case, Pass by reference (objects)

c = {"name" : "jane"}; 
console.log(c); // { "name" : "jane" }    
console.log(d); // { "name" : "doe" }
  • The equal(=) operator sets up new memory space or address
Ashish Singh Rawat
  • 1,419
  • 16
  • 30
0

Basically, In JavaScript, there is no concept of Pass-By-Reference because Pass-by-value serves the purpose which makes JS so special. when we pass an object in JavaScript, 1)function needs to with the value and that value is the reference copy 2)This value to the address of the original object.

0

How can I handle this problem? What if I want to change the object itself rather than its copy reference?

I wanted to reassign an object within a function and its new value be visible in the calling function.

To add to the great accepted answer, and address unanswered questions in comments there, here's my take on passing by reference with a look at scope / closure in practice:

const obj = {
  count: 0,
}

function incrementReference(_obj) {
  obj.count++
}

function createIncrementByCopy(_obj) {
  let inner = {}
  Object.assign(inner, _obj)

  return function increment() {
    inner.count++
  }
}

function createScopedIncrement(_obj) {
  return function increment() {
    _obj.count++
  }
}
function createExtend(_obj) {
  return function increment(ext) {
    Object.assign(_obj, ext)
  }
}

console.log('obj', obj) // { count: 0 }

incrementReference(obj)
console.log('incrementReference ✅', obj.count) // 1

const incrementCopy = createIncrementByCopy(obj)
incrementCopy()
console.log('incrementCopy ❌', obj.count) // 1

const incrementA = createScopedIncrement(obj)
incrementA()
console.log('incrementA ✅', obj.count) // 2

const extendObj = createExtend(obj)
extendObj({ text: 'New Property!' })
console.log('extendObj ✅', obj) // { count: 2, text: 'New Property!' } 

The following article discusses a common confusion about the terminology, which I really can't speak to https://dev.to/bytebodger/a-gotcha-of-javascript-s-pass-by-reference-1afm

Related (good context, more complex, different use case): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#copying_accessors

ptim
  • 14,902
  • 10
  • 83
  • 103