What is the reason behind certain cases where the properties of an object undergo mutation when passed into a function, while others remain unaffected?

I am puzzled by the behavior of mutability and immutability when assigning values to variables in JavaScript. I have observed four cases with varying results, some mutating the value while others do not. Can anyone provide a clear explanation on how this concept really works? It seems like a common interview question, but I struggle to articulate it...

Case 1

const x = { a: 1, b: 2 };
function fn1(_x) {
    _x.a = 0;
}
fn1(x);
console.log(x);
// { a: 0, b: 2 }          mutated

Case 2

const y = { a: 1, b: 2 };
function fn2(_y) {
    _y = 0;
}
fn2(y.a);
console.log(y);
// { a: 1, b: 2 }          not mutated

From these code samples, it appears that the value of an object's property cannot be changed if not explicitly assigned within the function.


Case 3

const z1 = { a: 1, b: 2 };
function fn3({ a }) {
    a = 0;
    a.c = 0;
}
fn3(z1);
console.log(z1);
// { a: 1, b: 2 }          not mutated

Case 4

const z2 = { a: {}, b: 2 };
function fn3({ a }) {
    a = 0;
    a.c = 0;
}
fn3(z2);
console.log(z2);
// { a: {}, b: 2 }         not mutated

In Case 4, I expected { a: {}, b: 2 }. Why is the value of z2 mutated but z1 remains unchanged? Could it be because String and Number are immutable?


Based on these experiments, can I conclude that a value will only change if explicitly assigned to a property of an object within a function? I also assume that the behavior of arrays follows the same rules as objects.

Thank you!


UPDATE:

Case 5

const z2 = { a: {}, b: 2 };
function fn4({ a }) {
    a.c = 0;
    a = 0;
}
fn3(z2);
console.log(z2);
// { a: { c: 0 }, b: 2 }        mutated

Patrick Roberts pointed out that the previous Case 4 was actually not mutable, which I had overlooked... However, what caught my interest was that by changing the order of a.c = 0; and a = 0; in Case 5 (now fn4), the output changes... but at this point I'm stuck. Apologies for the error in Case 4.

Answer №1

When it comes to situation 1, you're providing a reference to an object and modifying one of its properties, whereas in situation 2, you're passing a value to the function and performing an action on it. The variable _y is only accessible within the scope of fn2(_y); it does not exist beyond that point. Therefore, calling fn2(y.a) is essentially the same as calling fn2(1), meaning there is no alteration to the original y.

Situation 3 and Situation 4 both utilize the new object destructuring syntax, making these two codes equivalent:

function fn3({ a }) {
    a = 0;
    a.c = 0;
}

function fn3(x) {
    var a = x.a;
    a = 0;
    a.c = 0;
}

Thus, invoking fn3 in situation 3 acts as pass by value, similar to Situation 2.

Situation 4 does not modify the object.

UPDATE SITUATION 5

const z2 = { a: {}, b: 2 };
function fn4({ a }) {
    a.c = 0;
    a = 0;
}
fn4(z2);
console.log(z2);

In Situation 5, you are encountering the phenomenon of "hoisting." This code does not execute in the exact sequence it appears. In JavaScript, declaring any variable is synonymous with declaring it at the top of the enclosing scope. For var, the enclosing scope will be the function, while for let and const, it will be the curly brackets. Consequently, the previous code can be translated into this form:

const z2 = { a: {}, b: 2 };
function fn4(x) {
   var a = 0;
   x.a.c = 0;
}
fn4(z2);
console.log(z2);

This occurs because when you declare a = 0, it gets hoisted to the top of the function. The a obtained from the parameter refers to a distinct a, specifically a reference to the a property from the object passed to the function.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to retrieve text content from a modal using JavaScript?

I am using ajax to fetch values from my table. $(data.mesIzinTanimList).each(function (index, element) { if (element.izinTanimiVarmi == 'yok') tr = "<tr class='bg-warning text-warning-50' row='" + element. ...

Patience is key as we wait for another observable to finish using await

Hi everyone, I am facing an issue in my Angular app where I have two methods getA and getB. I have added a third method getC which is dependent on the results from getB. Can someone guide me on how to properly wait for getB to complete before executing g ...

Is it possible for webdriver to retrieve the URL of the style sheet being utilized by a specific element?

Currently, I am working on a test scenario where I need to confirm that altering an option in a dropdown menu modifies the styling of the page. I am curious if Webdriver has the ability to retrieve the URL of the CSS document from an element. This appear ...

Setting the values of a string array to the properties of an object dynamically in TypeScript

Imagine a situation where a component called searchBox is given two inputs: @Input() titles: string[] and @Input() model: Object. The number of values in the titles array matches the number of properties in the model object. The searchBox component generat ...

The Angular view doesn't automatically refresh when using the standard JavaScript setInterval function

As a beginner in Angular 2 while working on an app, I encountered an issue with updating the variable value on the view using the setInterval() function. The function runs as expected but the view does not reflect the updates of the 'title' varia ...

What is the specific order in which Vue.js components are created using the Created() method

When two components are loaded into a third component, what dictates the sequence in which the lifecycle methods for each component will execute? Main Component <template> <div> <component-a /> <component-b /> ...

Are Primereact and MUI JOY Styling at Odds?

here is the image of datatables and button I am currently using Primereact and MUI Joy in the same project, but I am facing an issue where the Primereact styling does not load properly. I'm not sure if it's due to a conflict with MUI Joy or some ...

Create an array of dynamically calculated properties from the Vuex state array, which can then be utilized in the v-model

In my Vue 3 setup, I have a Vuex store with an array in the state: const store = createStore({ state: { questions: [ { text: 'A', value: false }, { text: 'B', value: false }, { text: 'C', value: true }, ...

How to reference a function from an external JavaScript file using jQuery

Is it possible to call a function from my master .js file within my php page? <script type="text/javascript> functionName(); //attempting to call function from master.js file </script> Unfortunately, it doesn't appear to be working. ...

Troubles with Vue and localStorage for storing a theme's data

I've been struggling with this issue for a while now while working on a Vue site. I have not been able to find a solution for my specific bug in other discussions. The concept should be straightforward - I want to have a switch that toggles a value b ...

Change the keys of the object in the return statement

Scenario Imagine a scenario where a method called matter is returning an object in the form of return {content, data} Issue There is a conflict when the method is called a second time, as it overwrites any previous variables that were set from the return ...

Adding a DOM element within a React component

In my project, I am using Django for both the backend and most of the frontend, with the exception of one form that is built in ReactJS. To improve the loading speed of this specific form, I want to fetch its data directly from the HTML instead of making a ...

Encountered an error in Discord.js: Undefined properties unable to be read (execute)

Here is the code snippet from my main file: const { Client, IntentsBitField, Collection, intents, SlashCommandBuilder } = require('discord.js') const { TOKEN, PREFIX } = require('./config.json') const fs = require('fs'); const ...

Node JS: Despite modifying the URL, the response remains unchanged

My attempt to log in to teeSpring.com and retrieve a response from another URL using a login cookie seems to be causing an issue. Upon logging into teeSpring.com, the dashboard details are returned. However, when I try to make a GET request to the second U ...

Strings holding special arrangements of breaks in between

Currently, I am developing a portal that enables examiners to provide a problem statement, sample input, and sample output. However, I am facing an issue where the sample input/output values are stored as complete strings, causing line breaks to not render ...

"Enhance your website with a dynamic animated background using Bootstrap container

I'm struggling to understand why the Bootstrap container is blocking the particles-js animation behind the text. I want the background surrounding the text to be animated as well... :/ Example Code: .gradient-bg { background: rgba(120, 87, 158, ...

When the text exceeds the space available, it will automatically flow into a new column in lower

Is there a way to make text content flow into a column that appears next to it when the window height is decreased? Essentially, I am looking for a solution where the text can smoothly transition to a dynamically created column. Are there any jQuery plugi ...

Upon retrieving the Firebase storage link, the page automatically refreshes

When working on a page form, I am able to successfully edit and save data back to Firebase. The text fields work fine for editing data. Additionally, this page form includes images that are displayed based on links retrieved from Firebase storage. There a ...

What is the best way to retrieve the overall error status from the Material UI DataGrid?

I am currently utilizing the Material UI DataGrid element to display information from an EXCEL file. Each Excel document consists of numerous column titles with specific types assigned to them. As an example: const columns = [ { "field&quo ...

Altering pointer during drag操作

Is it feasible to customize the cursor during a drag operation? I've been exploring ways to achieve this for some time now. My goal is to replace the default 'not-allowed' cursor that appears when dragging an object with a different cursor. ...