FAQ: Objects - Pass By Reference

The explanation object -pass by reference concept is confusing .
In the codecademy code example i added a line and am getting ‘Earth’ inside the function but the object in function reassignment fails as stated. So codecademy explanation does not make sense:" When we passed spaceship into that function, obj became a reference to the memory location of the spaceship object, but not to the spaceship variable. This is because the obj parameter of the tryReassignment() function is a variable in its own right. The body of tryReassignment() has no knowledge of the spaceship variable at all!" what now???

If the " The body of tryReassignment() has no knowledge of the spaceship variable at all!" then how come my obj.homePlanet returns Earth? And after reassignment returns Undefined.
please clarify
Thanks

let tryReassignment = obj => {
console.log(obj.homePlanet); // Earth <— I added this Line

obj = {
identified : false,
‘transport type’ : ‘flying’
}
console.log(obj.homePlanet); // Prints : Undefined <------ i added this
console.log(obj) // Prints {‘identified’: false, ‘transport type’: ‘flying’}

};
tryReassignment(spaceship) // The attempt at reassignment does not work.
spaceship // Still returns {homePlanet : ‘Earth’, color : ‘red’};

spaceship = {
identified : false,
‘transport type’: ‘flying’
}; // Regular reassignment still works.

To Force it to work as I want it to I added return obj and then assigned returned object to spaceship and following works!!! (but the previous confusion still needs clarification):
let spaceship = {
homePlanet : ‘Earth’,
color : ‘red’
};

let tryReassignment = obj => {
obj = {
identified : false,
‘transport type’ : ‘flying’
}
console.log(obj) // Prints {‘identified’: false, ‘transport type’: ‘flying’}
return obj; //<---- I added this line

};
spaceship = tryReassignment(spaceship) // WORKS!!! { identified: false, ‘transport type’: ‘flying’ } <---- I added this line
console.log(spaceship) // Prints { identified: false, ‘transport type’: ‘flying’ }

spaceship = {
identified : false,
‘transport type’: ‘flying’
}; // Regular reassignment still works.
console.log(spaceship) // Prints {‘identified’: false, ‘transport type’: ‘flying’}

To preserve code formatting in forum posts, see: [How to] Format code in posts
Your code:

let spaceship = {
  homePlanet : 'Earth',
  color : 'red'
};

let tryReassignment = obj => {
  console.log(obj.homePlanet); // Earth <— I added this Line
  obj = {
    identified : false, 
    'transport type' : 'flying'
  }
  console.log(obj.homePlanet); // Prints : Undefined <------ i added this
  console.log(obj) // Prints {'identified': false, 'transport type': 'flying'}
 
};
tryReassignment(spaceship) // The attempt at reassignment does not work.
spaceship // Still returns {homePlanet : 'Earth', color : 'red'};
 
spaceship = {
  identified : false, 
  'transport type': 'flying'
}; // Regular reassignment still works.

You can right click, open the images in new tabs and zoom for better readability,



Once you make the function call tryReassignment(spaceship), the memory location of the object assigned to the variable spaceship will be assigned to the parameter obj. The parameter obj will hold the memory location of the object, it will have no knowledge that the same object is also assigned to the variable spaceship.

console.log(obj.homePlanet); // Earth

The object that obj points to has a property named homePlanet with a value of "Earth", so this value is printed.
You then assign a new object (not mutating/modifying existing object) and assign it to obj. This new object has identified and 'transport type' as properties, but doesn’t have any property named homePlanet, therefore

console.log(obj.homePlanet); // undefined

will print undefined.

2 Likes

Thank you for the clarification.appreciate it!

1 Like

Thanks for the hint. The Medium article made it click for me.

Hi all, I’m on the section of Pass By Reference JavaScript,
Write a function greenEnergy() that has an object as a parameter and sets that object’s 'Fuel Type' property to 'avocado oil'
the anwner is : let greenEnergy = obj => {
obj[‘Fuel Type’] = ‘avocado oil’;

however, my own code is :
let greenEnergy = obj =>{
obj = {
‘Fuel Type’: ‘avocado oil’
}
}

what is the difference?

This is a, ‘Whoa! moment.’ Take a closer look at what your code is doing. It’s obliterating the input by reassigning the parameter value.

thank you for your reply, to confirm, an object cannot be inside of another object?

and why the below code works(it is an example from the codecademy course):

let tryReassignment = obj => {
obj = {
identified : false,
‘transport type’ : ‘flying’
}
console.log(obj)

Not inside another object, but it can be the value of an object property:

obj = {
    innerobj: {

    }
}

Looking at your other question, now. Not sure what the objective of the lesson is, but using your example,

 > let tryReassignment = obj => {
     obj = {
       identified: false,
       'transport type': 'flying'
     }
     console.log(obj)
   }
<- undefined
 > a = { one: 1 }
<- {one: 1}
 > tryReassignment(a)
   {identified: false, transport type: 'flying'}
<- undefined
 > a
   {one: 1}
 >

Note that a does not get reassigned. This is because the parameter has been reassigned so there is no binding to a. It makes no sense to take an object as parameter and then reassign the variable. Again, I’m not sure what the aim of the exercise is.

thank you! I get it now, it cannot be reassigned inside another object. the example given was to illustrate it doesn’t work. it now makes more sense.
btw, the lecture was trying to teach object pass by reference

1 Like


Why are curly braces needed in line 8 but not line 11? Is it that they are mandatory if there is a string even in a single line

In this particular piece of code, the presence or absence of curly braces does make a difference but the functions accomplish their task in either case. You could have written both functions with curly braces or both functions without curly braces. If you wished, you could have written the second function with curly braces as well. Similarly, you could have omitted the curly braces from the first function if so inclined.

The presence or absence of curly braces does make a difference to the return values.

  • If curly braces are used for the body of an arrow function and we wish to return some value, then we must do so explicitly by using the return keyword.
  • If curly braces are not used for the body of an arrow function, then the value will be implicitly returned (and we aren’t allowed to use the return keyword).

The greenEnergy and remotelyDisable functions are meant to set/re-assign the values of certain properties of an object i.e. the functions are meant to mutate/modify the object. The return values of the functions (in this particular exercise) are not important. If the specifications required the functions to return some values as well, then the absence/presence of curly braces would be an important detail.

In your screenshot, curly braces have been used for the greenEnergy function. Since no return keyword has been used in the body of the function, so there is no explicit return. Instead, the function’s return value will be undefined. If the return keyword had been used, then the return value of the function would be the string "avocado oil".
No curly braces have been used for the body of the remotelyDisable function. After the assignment, the expression obj.disabled = true; evaluates to true and so the boolean true is implicitly returned by the arrow function.

let spaceship = {
  'Fuel Type' : 'Turbo Fuel',
  homePlanet : 'Earth'
};

// Your functions from screenshot here
// ...

console.log(greenEnergy(spaceship));
// undefined

console.log(remotelyDisable(spaceship));
// true

console.log(spaceship);
// { 'Fuel Type': 'avocado oil', homePlanet: 'Earth', disabled: true }

If the return values of the functions are important, then the absence/presence of curly braces makes a difference. In the exercise, the two functions are meant to mutate/modify the object and the return values aren’t important, so you can choose to omit or include the curly braces as you deem suitable.

1 Like

Thank you so much, I see why you’re a Gold Problem Solver. Incidentally earlier today I realized I don’t really get the difference between using/not using return. I thought it had to do with wanting to achieve what console.log does but not print it, or concise syntax. Turns out also return is not used when we are setting a value. In my head the mnemonic is if I see a = it’s probably not a case where return is needed. So thank you, you explicitly confirmed it. I guess my issue was that the solution wasn’t accepting my ‘curly braces in both’. But good to know it’s actually correct.

Yeah, it has been more than 4 hours and this part still confuses me the most for several reasons:

  • It never explained what ‘reference’ means, does it means that ‘obj’ variable value is the memory address of spaceship object is the or the variable?
  • In case for former, then we can assume that the variable value always point to same memory address of object no matter how many it passed to any variables, this is maybe different from simple data value which even the same can reside in different memory address. change in ‘pass by value’ won’t affect others contrary to ‘pass by reference’
  • The main problem is: because it arises despite uses of ‘let’ and not ‘const’, why it cannot be reassigned as in the simple block scope? this is arguably the most confusing one.
  • Is it not re-assignable because the value of ‘obj’ variable must only in form of memory address? it doesn’t make sense, except if maybe it is declared by ‘const’.
  • Part of ‘has no knowledge’ is in my opinion irrelevant. It has access to object memory, that is what matter right? (back to the main problem)

In conclusion: IMO ‘pass by reference’ should make permanent change as the explanation suggest (and should not be just modification, reassignment too). Reassignment should be able to change the value too, why error occur here and not in modification of property? The explanation is not clear, and the content writer should clarify this because this is one of the most important concept.

Any variable that refers to an object in the namespace is a reference.

a = 42

The number, 42 is stored somewhere in memory. The system looks after allocating space and stores the address in the heap. The variable a points to the heap to find that memory address. There is a chain that connects the variable to the heap and the heap to the object. This is a general description of a reference.

If we assign a new value to a, the old reference is lost, and the memory manager marks the old value for garbage collection. a will have taken on a new reference.

To come to grips with this concept we need to erase the origin idea we may have been taught at the beginning:

42 is stored in a

False, and it shouldn’t be taught that way except most teachers do not want to get bogged down in the details when just getting started with JS (or programming).

Nothing is stored in a. It is a label we have given to name our value, which is actually the name of the address in the heap, wherein the memory address of the value is stored.

If you’ve got past learning about objects, that is, key-value pairs, we can think of a variable as a key.

a: 112244551122

The number is a pseudo representation of the address in the heap.

Now, another variation of reference comes up when dealing with functions, that of objects that are non-primitive such as arrays, objects and functions. We do not pass those objects into a function, they stay where they are in memory. The only thing given to the function as an argument is the reference, and we can give it a local name for convenience and readability. Regardless the name we give it (parameter) it will still refer to the actual object. The name may be different, but the object is the same, therefore both the original variable name and the parameter name we give it point to the same address in the heap.

This gets even more confusing when we bring up the other side of memory management in JS, the stack, or call stack. This is where functions are referenced. The mechanics are similar to objects and arrays, but functions have a return so the internal workings are a bit different.

Before I completely go off the rails and confuse you even further, see if your can find some reading on the subject of JS heap and stack.

1 Like

Maybe i can summarize in my own terms a bit (CMIIW):

  • reference is pointer, it refers to location in the heap-memory and not the object itself.
  • mutation of original object is possible(maintaining same space). either the changes is not concern the whole object (only the property etc.) or still connected to old object (like increment etc.)
  • when we reassigned parameter in function, parameter(if the name is not same as original), it will refer to totally different heap-memory and become independent of original variable. that’s why the global variable is unaffected when passed.

I even rethinking the concept of mutability again, what mutable is and what it really means to change/mutate the value.
Why reassignment won’t reuse the same memory space in case of type safe languages like C or Java? Doesn’t really matter for me now. mutability is really independent of declaration existence or language type-safety. Reassignment -as you said- make different reference, even in mutable data types in any language.

it really push me to clarifies many concepts i think i understood.

Not if it is a primitive. We can only mutate reference objects, namely the elements of an array or the items of an object. This is where reference actually means something tangible since we see the entire data structure is built upon the referential model. It’s easy to think of if we put the mechanics in the system’s hands.

A value is stored in memory, somewhere. The system knows where it is (transitory fix) long enough to place the address in the heap, notwithstanding there is a reference awaiting it. Without a reference, there is no point in placing the address in the heap. Kick it aside. We can see this is actually quite complicated.

The value that is stored can never be changed. Where it is stored in memory will never be visited again. That memory, once it loses all references will be marked for garbage collection and memory freed up. If we assign a new primitive value to a variable, the variable gets a brand new heap pointer and the heap gets a brand new address pointer.

This is where is gets less fuzzy, once we turn our attention to arrays and objects. They are mutable (keys are not) because what gets mutated is the reference in the array element, or object{key] value. We haven’t moved the position of a indexed array element, or the manipulated object beyond a value change, perhaps. Things are as they were, structurally, but the references held in the modified elements/values are indeed mutated.

I’ve wandered off and got away from your narrative, so give me a minute to continue reading it. Go ahead and comment on this post. I’ll start a new reply.

Oh yeah, I didn’t skip your first point. just agree with it.

1 Like

Even incrementing, while it appears to us as ‘in place’ is not in situ, but a new address and new heap address and new assignment. The revolving door approach is how memory maintains its optimization at all times. References change all the time as new values stream into memory that has been newly allocated. Fortunately for us, we don’t have to consider any of this, thank providence for that.

Bottom line, memory locations and their contents are not mutable. If we change the value, we change the location. It makes references and pointers a definite necessity.

Going to keep reading your post, and editing this one… PSB

That only applies to primitives. In the function call process a namespace is created for that function and any primitive references, such as,

const foo = function (x) {
    return x
}

y = foo(42)

On my old Timex the memory address for that literal would literally be where it is in the written code. That is the address that would be given to the heap. JS might even work that way, too, in the case of literals, who knows? It makes sense to.

x = 42
y = foo(x)

As it happens, y is independent from x even while it refers to the same primitive value. That is because the returned value reference is to a different heap. This is more or less explained by ‘scope’ (with provisos, of course).

If we change what x refers to it will have no affect on y, neither inside nor outside of the function. This all gets switched around when x is an array or an object. They are now data structures, not primitives and they play by different rules, though not as abstract as we might think. We’ve already covered the general idea.

We don’t store values IN an array, we store reference pointers, as in heap addresses or stack pointers. Over and above all this mechanics we are relieved of any need to understand further, for the purpose of learning and mastering this language. The juicy stuff doesn’t come up until you’re in right up to your neck in the engineering side of things. We’re lucky to have such useful and easy to use language with all the messy stuff well tucked away in the background.

That is out of our scope, but the real difference is those languages are compiled so they have a complete image of all the utilized memory, already. JavaScript is script and memory is constantly being requested and allocated and garbage collected. It’s a revolving door. Much easier to just allocate new memory for the latest assigned value. The heap takes care of interfacing.

Keep working to clear up any questions you have with respect to mutability and how it actually happens at the system level. It won’t help if you are hanging on to the original location of a value and trying to change it. That won’t happen. Not the way JS works.

I’m glad you’re really diving into this and hope we’re not muddying up the water or hitting you with too much. You can, for the most part, relieve yourself of this topic once you’ve absorbed it. It shouldn’t need to come up again. Keep up with your study path, and add this to your future reading when you are better able to dive deeper. Maybe then you can educate me and set me straight on any errors in what I’ve described above. If I’ve got the wrong notion, it should be rectified. But for now, I’m cool to be right or wrong, so long as we can say we’ve given it a good kick at the can and opened new pathways of understanding, subject to change, albeit.

1 Like

I think i should just continue finishing this and FSE path first.
I will definitely come back to this, very appreciate for all CA teams.
Best Regards

1 Like