Using forEach to iterate through objects presents challenges when attempting to make changes

What is the reason behind the success of the first modification (when reassigning properties of the object) but the failure of the second modification (when reassigning the whole object)?

const arr1 = [
    { id: 1, value: 1 },
    { id: 2, value: 2 },
    { id: 3, value: 3 },
    { id: 4, value: 4 },
    { id: 5, value: 5 },
]

arr1.forEach((item, index) => {
    if (item.id === 1) {
        item.value *= 10   // successful modification
    }
});

console.log(arr1);

arr1.forEach((item, index) => {
    if (item.id === 1) {
        item = {id:6,value:6}  // unsuccessful modification
    }
});

console.log(arr1);
.as-console-wrapper { max-height: 100% !important; top: auto; }

Answer №1

Below is an example to consider:

Firstly, we create an object and assign it to a variable foo. Afterwards, we assign foo to bar. This results in both foo and bar referring to the same object, as shown in the diagram below.

let foo = { id: 1, val: "foo" };
let bar = foo;

https://i.sstatic.net/yIYoj.png

Next, we modify the val field of the object that bar is pointing to. This change is mirrored in both variables foo and bar because they both reference the same object.

let foo = {id: 1,val: "foo"};
let bar = foo;
bar.val = "bar";
console.log(foo, bar);

https://i.sstatic.net/9mn8A.png

Subsequently, we assign a new object to bar. It's important to note that this action does not impact the object that foo is linked to; rather, bar now references a different object.

let foo = { id: 1, val: "foo" };
let bar = foo;
bar = { id: 1, val: "bar" };
console.log(foo, bar);

https://i.sstatic.net/ly88y.png

To connect this concept to the forEach example in your query, during each iteration of the forEach loop, the item parameter in the callback function points to an object from the array. Altering a field in this item parameter will impact the corresponding object in the array. However, assigning a new object to item will not affect the object in the array.

If you wish to substitute the entire object with a new one, there are various approaches to consider, two of which are outlined below:

  1. Locating the index where the object is stored and replacing it with a new object.

const arr = [{ id: 1, value: 1 }, { id: 2, value: 2 }, { id: 3, value: 3 }, { id: 4, value: 4 }, { id: 5, value: 5 }];

const index = arr.findIndex((obj) => obj.id === 3);
if (index !== -1) {
  arr[index] = { id: 6, value: 6 };
}

console.log(arr);

  1. Another common approach is to use map to create a new array with the desired object replaced.

const arr = [{ id: 1, value: 1 }, { id: 2, value: 2 }, { id: 3, value: 3 }, { id: 4, value: 4 }, { id: 5, value: 5 }];

const newArr = arr.map((obj) => (obj.id === 3 ? { id: 6, value: 6 } : obj));

console.log(newArr);

Answer №2

It's common to feel confused about the difference between an actual object and a variable.

When using a foreach function, the variable "item" refers to the object in the array being looped through. However, when you reassign the variable with {id:6,value:6}, you are not altering the original object but creating a new one.

If you want to modify the object itself, you can manually change its values or use Object.assign to copy values from another object.

For examples demonstrating this concept and specifically addressing your scenario, check out the link to Object.assign.

In the provided code snippet, I've included various scenarios to help clarify the distinction, and I've solved your specific case using Object.assign().

const a = { id: 1, value: 1 };
let b = a; // b now points to the same object as variable a

b = {id: 2, value: 2};

console.log('a', a, 'b', b) // output shows two different objects with different values

const c = {id: 3, value: 3};
const d = c;
Object.assign(c, {id: 4, value: 4});
console.log('c', c, 'd', d); // c and d both have id: 4 and value: 4 because they both point to the same object

const e = { id: 5, value: 5 };
const f = e;
e.id = 6;

console.log('e', e, 'f', f); // directly assigning the value also works

// More code examples...

Answer №3

When using forEach to iterate over an array, the variable item holds a reference to the object being iterated over. This means that modifying item will directly affect the original object. However, if you reassign item to a new object within the loop, the original object remains unchanged.

For example, in the first code snippet, modifying the properties of item within the forEach loop will reflect those changes in the original array. On the other hand, reassigning item to a new object will detach it from the original array, preventing modifications.

const arr1 = [
    { id: 1, value: 1 },
    { id: 2, value: 2 },
    { id: 3, value: 3 },
    { id: 4, value: 4 },
    { id: 5, value: 5 },
];

arr1.forEach((item, index) => {
    if (item.id === 1) {
        item.value *= 10   // modify success
    }
});

console.log(arr1);

arr1.forEach((item, index) => {
    if (item.id === 1) {
        item.id = 6;
        item.value = 6;
    }
});

console.log(arr1);
.as-console-wrapper { max-height: 100% !important; top: auto; }

You can also dynamically reassign properties by looping over an object and updating its properties within the forEach loop:

const arr1 = [
    { id: 1, value: 1 },
    { id: 2, value: 2 },
    { id: 3, value: 3 },
    { id: 4, value: 4 },
    { id: 5, value: 5 },
];

arr1.forEach((item, index) => {
    if (item.id === 1) {
        item.value *= 10   // modify success
    }
});

console.log(arr1);

arr1.forEach((item, index) => {
    if (item.id === 1) {
        let toConvert = { id: 6, value: 6};
        Object.entries(toConvert).forEach(([k, v]) => item[k] = v);
    }
});

console.log(arr1);
.as-console-wrapper { max-height: 100% !important; top: auto; }

Answer №4

When looking at the first scenario, it can be interpreted as:

const it = { value: 10 };
const item = it;
item.value = 11;
console.log(it);   // item and it both reference the same object, resulting in the modification of the object's property value

Now, let's examine the second situation:

const it = { value: 10 };
let item = it;           // Initially, both item and it point to the same object
item = { value: 6 };     // However, item now refers to a new object while it remains connected to the original
console.log(item, it);   // As a result, it remains { value: 10 }, while item is now { value: 6 }

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

What is the best way to save the response data into an array outside of the current function in Node.js?

How can I efficiently store all the result data into an array called pImages? I am able to retrieve the results, but I believe using an async function would be more suitable. However, I am unsure of how to implement it. Any assistance would be greatly appr ...

Validate forms using jQuery with the power of ajax

Is there a way to effectively check for the existence of a username? I want to increment a variable called "form_error" if the username already exists. If "form_errors" is greater than 0, I need the code to stop and return false. However, when I use an Aj ...

Failed validation for Angular file upload

I attempted to create a file validator in the front end using Angular. The validator is quite straightforward. I added a function onFileChange(event) to the file input form to extract properties from the uploaded file. I then implemented a filter - only al ...

What is causing the col divs to stack instead of aligning next to each other?

I am a newcomer to Vue.JS and front-end programming in general. I wanted to create a page with a fixed sidebar and content below a navbar. Here is the configuration I tried: <template> <div class="container-fluid"> <div class ...

Updating a nested property within an array of objects in MongoDB

Storing grades for an online education application using MongoDB. Here is a sample classRoom document stored in my mongoDB database. StudentGradeObjs are kept in an array within a GradeObject. GradeObjs are stored in an array of GradeObjects inside a class ...

Embed your JavaScript code within the header tags of the WooCommerce order confirmation page

Seeking to enhance my thank you page with Google tracking script, I have developed code that successfully injects the tracker within the of the page, incorporating dynamic values. However, my goal is to embed it within the tags instead. function mv_goog ...

The issue with ng-if not functioning within ng-repeat is that the ng-if directive

My issue is with using ng-if inside an ng-repeat in AngularJS. Despite updating to the latest version on 09/27/2014, I am still unable to make it work properly. The code functions perfectly outside of ng-repeat, and also works fine inside ng-repeat when us ...

encase a function with javascript

let myString = "I am creating a program."; //function to calculate number of letters const letterCount = (str) => str.length; //function to calculate number of words const wordCount = (str) => str.split(" ").length; //function ...

Automatically insert a hyphen (-) between each set of 10 digits in a phone number as it is being typed into the text

I'm attempting to automatically insert a hyphen (-) in between 10 digits of a phone number as it is being typed into the text field, following North American standard formatting. I want the output to look like this: 647-364-3975 I am using the keyup ...

leveraging a callback function alongside the useState hook

I'm facing an issue with the change() function. My goal is to call the filteredData() function after the setState operation is completed. Typically, I would use a callback function for this task, but useState doesn't support callbacks. Using useE ...

Tips for preventing HTTP Status 415 when sending an ajax request to the server

I am struggling with an AJAX call that should be returning a JSON document function fetchData() { $.ajax({ url: '/x', type: 'GET', data: "json", success: function (data) { // code is miss ...

How can I efficiently extract specific data from JSON using AngularJs?

In my array (_users), there are JSON objects. { "User": { "userid":"19571", "status":"7", "active":"1", "lastlogin":"1339759025307", "Stats": [ { "active":"1", "catid":"10918", "typeid":"71", ...

A guide on assigning specific (x, y) coordinates to individual IDs within the tree structure

When attempting to calculate the positions of each ID in order to arrange them hierarchically on the canvas, I encounter some challenges. Whether it's organizing them into a tree structure or multiple trees resembling a forest, one restriction is that ...

How to determine if a scrolling action is initiated manually using jQuery

Here is a question that was previously asked long ago: Detect jquery event trigger by user or call by code Despite previous inquiries, a conclusive answer has not been provided (or I may just be inadequate at searching). My query pertains to distinguish ...

Disable multiple buttons at once by clicking on them

What is the best way to disable all buttons in a menu when one of them is clicked? Here is my code: <div class="header-menu"> <button type="button"> <i class="fa fa-search" matTooltip="Filter"& ...

Storing JavaScript object in a database using a PHP script

My current scenario involves having a JavaScript object which can be converted into JSON format using the stringify method. Here's how it looks: var jsObject ={'elem1':'val1', 'elem2': {'elem21':'val1&apos ...

Removing elements from an array if it includes a certain string in Hive/SparkSQL

Looking at the sample data provided, I aim to extract elements that only contain names and their completed keys without any dep_names and its corresponding completed key. Here's my approach: WITH dataset AS ( SELECT '{"name": " ...

Change to a dark theme using React hooks in typescript

Hello, I am new to React and English is not my first language, so please excuse any mistakes. I have been trying to enable a dark mode feature on my website. Most examples I have found involve toggling between dark and light modes where you need to specify ...

Turn off link preview feature on Android messages

As a developer, I am looking for a way to disable or hide link previews on Android devices when someone receives a text message with a link to our website. I still want the URL address to be visible, but I prefer to keep the link previews on IOS devices. I ...

Creating an Angular JS controller that utilizes a filter for a JSON array of objects

I have the following JSON data and I'm trying to determine the number of objects with Status: 1 in the JSON. The approach I've taken so far is not working. I understand that ng-filter should only be applied to Arrays, but I'm struggling to ...