Reputation: 13
So simplified code.
var a = [
{ name: "first", num: 1 },
{ name: "first", num: 2 },
{ name: "first", num: 3 },
{ name: "first", num: 4 },
{ name: "first", num: 5 },
{ name: "first", num: 6 },
{ name: "first", num: 7 },
{ name: "first", num: 8 },
{ name: "first", num: 9 }
];
var b = a.filter(function(el) {
return el.num % 2 == 0;
});
console.log("a1", a); // [1, 20, 3, 40, 5, 60, 7, 80, 9]
console.log("b1", b); // [20, 40, 60, 80]
for (let i = 0; i < b.length; i++) {
b[i].num = b[i].num * 10;
}
console.log("a2", a); // [1, 20, 3, 40, 5, 60, 7, 80, 9]
console.log("b2", b); // [20, 40, 60, 80]
My new understanding is the array element contains a reference to an object, not the object. What are some ways to get those objects duplicated?
Also, what's up with console.log() showing the variables have changed when placed before the for loop?
Upvotes: 1
Views: 92
Reputation: 81
A simple solution using some ES6 syntax:
var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3},
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7},
{name:'first', num: 8}, {name:'first', num: 9}];
const b = a
.filter(el => {
if (el.num % 2 === 0) {
return {
...el
}
}
})
.map(newEl => newEl.num * 10);
console.log('a', a); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('b', b);
return { ...el }
returns a cloned object thanks to spread
operator.Here some info about .map() .filter() and spread operator:
I found this very interesting site that lists all Javascript functions with their descriptions and shows if is mutable or not, this helps a lot: https://doesitmutate.xyz/
Upvotes: 0
Reputation: 21658
If you want a new array with the final values you can use reduce to do it all in one go, reduce starts with an accumulator of an empty array and each iteration if it meets the condition it adds a clone with the spread operator overriding the num time 10.
var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3},
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7},
{name:'first', num: 8}, {name:'first', num: 9}];
const evensTimes10 = array => array.reduce((results, item) => {
if (item.num % 2 === 0) {
results.push({ ...item, num: item.num * 10 });
}
return results;
}, []);
var b = evensTimes10(a);
console.log('a1',a); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('b1',b); // [20, 40, 60, 80]
Upvotes: 0
Reputation: 22365
Yes, elements of Array a
are all pointers. so you need to use Object.assign
(as many says)
and other solution with array reduce usage (see Adrian Brand comment)
var a = [ { name: 'first', num: 1 }
, { name: 'first', num: 2 }
, { name: 'first', num: 3 }
, { name: 'first', num: 4 }
, { name: 'first', num: 5 }
, { name: 'first', num: 6 }
, { name: 'first', num: 7 }
, { name: 'first', num: 8 }
, { name: 'first', num: 9 }
]
var b = a.filter(el=>!(el.num%2)).map(el=>Object.assign({},el))
// other solution with reduce
var c = a.reduce((acc,cur)=>{
if (!(cur.num%2) )acc.push(Object.assign({},cur))
return acc
}, [])
ConsoleArrayNamNum('var a -1-',a) // [1,2,3,4,5,6,7,8,9]
ConsoleArrayNamNum('var b -1-',b) // [2, 4, 6, 8]
ConsoleArrayNamNum('var c -1-',c) // [2, 4, 6, 8]
for(let elm of b)
{ elm.num *= 10 }
ConsoleArrayNamNum('var a -2-',a) // [1,2,3,4,5,6,7,8,9]
ConsoleArrayNamNum('var b -2-',b) // [20, 40, 60, 80]
function ConsoleArrayNamNum(title,arr) {
console.log(title)
for(let elm of arr)
{ console.log(`{ name: '${elm.name}', num: ${elm.num} }`) }
}
.as-console-wrapper { min-height: 100% !important; }
Upvotes: 0
Reputation: 2948
If you wish to duplicate the objects inside the array, you should use the map
function.
var b = a.filter(val => val.num %2 === 0).map(val => Object.assign({}, val, { num: val.num * 10}));
The map function will return a new array with the value returned from the function. In this example, we are creating a new object Object.assign({})
and duplicating the existing object while changing the num
field.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Upvotes: 1
Reputation: 21658
If you want to clone objects you will need a clone function, I use this function
const clone = obj =>
Array.isArray(obj)
? obj.map(item => clone(item))
: obj instanceof Date
? new Date(obj.getTime())
: obj && typeof obj === 'object'
? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
o[prop] = clone(obj[prop]);
return o;
}, {})
: obj;
You can then clone the array with
let c = clone(b);
Which will be a new array where each object is a new clone.
var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3},
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7},
{name:'first', num: 8}, {name:'first', num: 9}];
var b = a.filter(function(el){return el.num%2==0 });
const clone = obj =>
Array.isArray(obj)
? obj.map(item => clone(item))
: obj instanceof Date
? new Date(obj.getTime())
: obj && typeof obj === 'object'
? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
o[prop] = clone(obj[prop]);
return o;
}, {})
: obj;
let c = clone(b);
console.log(b[0] === c[0]);
Upvotes: 1