Understanding the functionality of the Array.prototype.map() method when used with JavaScript Objects

Experimenting with code:

 let obj ={};
    let newItems = ["Apple", "Banana", "Carrot", "Donut"].map(item => {
        obj.count= Math.random()*item.length;
        obj.itemName= item;
        return obj;
    });
    console.log(newItems);

The output generated is:

(4) [{…}, {…}, {…}, {…}]
0: {count: 1.4648989727265578, itemName: "Donut"}
1: {count: 1.4648989727265578, itemName: "Donut"}
2: {count: 1.4648989727265578, itemName: "Donut"}
3: {count: 1.4648989727265578, itemName: "Donut"}
length: 4
__proto__: Array(0)

This result is not as expected. However, when I modify the code to:

let obj;
let newItems = ["Apple", "Banana", "Carrot", "Donut"].map(item => {
      obj = {
               count: Math.random()*item.length,
               itemName: item
            } ;
      return obj;
 });
 console.log(newItems);

The desired output is achieved:

(4) [{…}, {…}, {…}, {…}]
0: {count: 4.2813861024052615, itemName: "Apple"}
1: {count: 5.850654082147917, itemName: "Banana"}
2: {count: 6.646446034466489, itemName: "Carrot"}
3: {count: 1.7062874250924214, itemName: "Donut"}
length: 4
__proto__: Array(0)

Can someone explain why there is a difference in behavior between these two code snippets?

Answer №1

When looking at your initial example, it is evident that only a single object was created and then added to the array four times:

let obj ={}; // <===== Creates the one object
let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => {
    obj.count= Math.random()*el.length;
    obj.ingredient= el;
    return obj; // <===== Puts it in the array four times
});
console.log(newIngredients);

This approach resulted in each instance of obj.ingredient = el; updating the property value, overwriting the previous one.

The memory representation would resemble something like this:

...

Your second scenario involves creating a distinct object for each invocation of the map callback function, which is the correct behavior. It's worth noting that the use of the variable obj may be unnecessary and can be removed without affecting functionality. This revised version looks like this:

let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => {
    return {
        count: Math.random()*el.length,
        ingredient: el
    };
});
console.log(newIngredients);

Alternatively, you could utilize a concise arrow function like this:

let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => ({
    count: Math.random()*el.length,
    ingredient: el
}));
console.log(newIngredients);

Answer №2

This discussion isn't about Array.prototype.map(), but rather focuses on the behavior of Objects in JavaScript.

Take a look at this example:

let obj = {};
let prev = obj;
let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => {
  obj = {
    count: Math.random() * el.length,
    ingredient: el
  };
  if (obj === prev) {
    console.log(true);
  } else {
    console.log(false)
  }
  prev = obj;
  return obj;
});
console.log(newIngredients);

Now, look at this variation:

let obj = {};
let prev = obj;
let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => {
  obj.count = Math.random() * el.length;
  obj.ingredient = el;
  if (obj === prev) {
    console.log(true);
  } else {
    console.log(false)
  }
  prev = obj;
  return obj;
});
console.log(newIngredients);

In the first example, you can see that it returns false due to the difference in Object creation syntax - using let a = { } compared to let a = new Object();.

In the correct version, you are simply updating the existing object referenced by all elements in the array, resulting in them all being updated simultaneously.

I hope this clarifies things for you.

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

Incorporate zoom feature into the jQuery polaroid gallery

Currently, I am utilizing a jQuery and CSS3 photo gallery found on this website. My goal is to allow the images to enlarge when clicked, however, the method provided by the author isn't very clear to me, as I'm not an expert in jQuery. I attempt ...

Duplicate a DOM element and incorporate animation into it

After extensively researching articles and documentation on this topic, I have yet to find a solution that aligns with the approach I am attempting to implement. My scenario involves an array of category items which contain a nested array of products be ...

What is the best method to determine the mean score by utilizing the ID values obtained from API responses?

These are the responses retrieved from the API: const attractions = [ {"id": 1,"name": "drive on avenue"}, {"id": 2, "name": "diving"}, {"id": 3,"name": "visiting ma ...

Issue accessing member value in inherited class constructor in Typescript

My situation involves a class named A, with another class named B that is inherited from it. class A { constructor(){ this.init(); } init(){} } class B extends A { private myMember = {value:1}; constructor(){ super(); ...

The perplexing behavior of RxJS Observables with Mongo Cursors

Recently, I've been working on converting a mongo cursor into an observable using my own RxJS implementation. Despite finding numerous solutions online, I wanted to challenge myself by creating one from scratch. I would greatly appreciate it if someo ...

JavaScript rearrange array elements

Currently, I'm attempting to move the values of an array over by a random amount. For instance: var array = [1,2,3,4]; var shiftAmount = 1; The goal is to shift the array so that it looks like [4,1,2,3] ...

Ruby organizes columns when generating a CSV file from Mongoid documents

I am trying to create a CSV document from my database. I have a specific order in which I want the columns to appear, and I already have a template stored as an array of headers. header = ["header1", "header2", "header3", "header4", "header5"] record = [{ ...

Error TS2322: The object with properties "ready: false" and "session: null" cannot be assigned to the type "Readonly<S & withAuthState>"

Here is the interface I'm currently working with: export interface withAuthState { ready: boolean, session: any } Additionally, I have developed the following Higher Order Component (HOC): const withAuth = <P extends withAuthProps, S extends ...

Associations in Typescript Sequelize

There are two simple models in a 1:N relationship - one student has many tasks. // StudentModel.ts interface StudentI extends Model<InferAttributes<StudentI>, InferCreationAttributes<StudentI>> { id: CreationOptional<number> ...

Display issue with Google Chart

Could someone please help me identify why these charts are not showing up? This code was functioning properly in a previous project. I copied the same code to a new project, only adding the master page. However, now the charts are not appearing. All I can ...

Ensure that only distinct elements are added to an ArrayList in Java

Currently, I'm working on a Java program that reads data from a text file and adds it to an array list. The issue I'm facing is that each time I run the program, the arraylist gets updated with duplicate elements - I want to ensure that each elem ...

Guide to configuring the initial lookAt/target for a Control

I'm looking to establish the initial 'lookAt' point for my scene, which will serve as both the center of the screen and the rotation control's focus. Ideally, I'd like to set a specific point or object position rather than rotation ...

Guide to retrieving variables stored in Local Storage using javascript and jquery while building an HTML form

In my HTML form, I have three select tags that create drop-down menus for the user. The total is calculated at the bottom of the form when a value is selected. Upon clicking 'save', the data is stored in local storage with four keys and their res ...

Invalid sequencing of Nest.js async onModuleInit causing issues

I am dealing with a scenario where ServiceA relies on RedisService. In order for ServiceA to be fully operational, it must wait for RedisService to complete its initialization process (specifically, for RedisService.onModuleInit to be called and awaited). ...

Set a unique class for several elements depending on a given condition

Is there a way to assign a color class based on the element's value without looping through all elements? Check out my jsfiddle HTML <div> <ul> <li class="MyScore">90</li> <li class="MyScore"> ...

How can I trigger a function by clicking on a link that was generated dynamically with jQuery?

I am dynamically creating multiple <a href="#"></a> elements with dynamically assigned id attributes like <a href="#" id='delete"+id+"'></a>. The IDs generated will be like delete01, delete02, .... I want to trigger a func ...

Alter the background of cards in real-time

I am unfamiliar with JavaScript, but I wish to utilize a function to alter the background color of multiple cards. function ChangeColorToGreen() { document.getElementById("ChangingCard").style.background = "green"; } function ChangeColorToPurple() { ...

Error: React JS is unable to access the property 'name' because it is undefined

I recently started working with React. The issue arises when I pass the array object into the map function, triggering an error. Below is the constructor where I've initialized the array object: constructor() { super(); this.state = { d ...

Remembering position in JSP using Java Beans

In my "Web Engineering" assignment, I am tasked with developing a Web Application game using JSP, Servlets, and Java Beans. The game mechanics are already in place with the Servlet controlling the algorithms, JSP handling the Model/View, and Beans managing ...

Just ran $npm install and encountered an error message: "Module '../lib/utils/unsupported.js' not found."

Returning to work on a React project after switching from the Rails environment, I encountered an issue where I am unable to run NPM commands in my Mac terminal. Despite trying various solutions I found online, none seem to be effective. The real concern i ...