Reputation: 57
I was trying the following code:
let obj ={};
let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => {
obj.count= Math.random()*el.length;
obj.ingredient= el;
return obj;
});
console.log(newIngredients);
and this is the output I get:
(4) [{…}, {…}, {…}, {…}]
0: {count: 1.4648989727265578, ingredient: "Love"}
1: {count: 1.4648989727265578, ingredient: "Love"}
2: {count: 1.4648989727265578, ingredient: "Love"}
3: {count: 1.4648989727265578, ingredient: "Love"}
length: 4
__proto__: Array(0)
This is not what I wanted. But when I type in the following,
let obj;
let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => {
obj = {
count: Math.random()*el.length,
ingredient: el
} ;
return obj;
});
console.log(newIngredients);
It returns the following output, which I actually want:
(4) [{…}, {…}, {…}, {…}]
0: {count: 4.2813861024052615, ingredient: "Hello"}
1: {count: 5.850654082147917, ingredient: "Distraction"}
2: {count: 6.646446034466489, ingredient: "Nothing"}
3: {count: 1.7062874250924214, ingredient: "Love"}
length: 4
__proto__: Array(0)
Can anyone please explain why is this difference in behavior between the two code snippets?
Upvotes: 2
Views: 210
Reputation: 1074148
In your first example, you only created one object, then put it in 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);
Since there's only one object, each time you did obj.ingredient = el;
you updated the property, replacing the previous value it had.
The result looks something like this in memory:
+−−−−−−−−−−−−−−−−−−−−−−−−−−−+ obj:Ref11654−−−−−−−−−−−−−−−−−−−−−−−+−+−+−+−>| (object) | / / / / +−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | | | | count: 1.4648989727265578 | | | | | | ingredient: "Love" | | | | | +−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | | | +−−−−−−−−−−−−−+ | | | | newIngredients−−−>| (array) | | | | | +−−−−−−−−−−−−−+ | | | | | 0: Ref11654 |−+ | | | | 1: Ref11654 |−−−+ | | | 2: Ref11654 |−−−−−+ | | 3: Ref11654 |−−−−−−−+ +−−−−−−−−−−−−−+
It's exactly like doing this:
let first = {};
first.a = 1;
let second = first;
second.a = 2;
console.log(first.a); // 2, not 1
Your second example creates an object for each call to the map
callback, which is correct, although there's no need for the obj
variable and having it is a bit misleading. So:
let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => {
return {
count: Math.random()*el.length,
ingredient: el
};
});
console.log(newIngredients);
or with a concise arrow function:
let newIngredients = ["Hello", "Distraction", "Nothing", "Love"].map(el => ({
count: Math.random()*el.length,
ingredient: el
}));
console.log(newIngredients);
Upvotes: 11
Reputation: 2044
This is not related to Array.prototype.map() but instead related to Object behaviour in javascript.
For example if you run this
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);
And run this
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);
You can clearly see in the first result, It's returning false because Object creation syntax, i.e
let a = { }
is equal to
let a = new Object();
In the true one, you're just updating the previous object which is the same object being referenced by all your array elements and being updated altogether.
Hopefully, this makes it clear.
Upvotes: 2