Spread syntax in an array of objects - javascript

I have a question regarding the spread syntax and an array of objects.
Having an array of objects like:
const array = [{age:50}, {age:27}]
According to this answer: https://stackoverflow.com/a/54138394/6781511, using the spread syntax will result in referencedArray having a shallow copy of array.
const referencedArray = [...array]
What then is the difference between using the spread syntax and not using it?
const referencedArray = [...array]
vs
const referencedArray = array

See the following example.
When you make a shallow copy, assigning to an element of the original doesn't affect the clone. When you don't make a copy, assigning to the original affects the other reference.
Since it's a shallow copy, assigning to properties of the objects in the array affects all of them. Only the array was copied by spreading, not the objects.
const array = [{age:50}, {age:27}];
const clonedArray = [...array];
const notClonedArray = array;
array[0] = {age: 100};
array[1].age = 30;
console.log("Original:", array);
console.log("Cloned:", clonedArray);
console.log("Not cloned:", notClonedArray);

The objects within the arrays have the same reference in both, but in the spread scenario, modifying the array will not affect the original.
const array = [{ name: 'Joe' }, { name: 'Paul' }];
const spreadArray = [...array];
const cloneArray = array;
spreadArray[3] = { name: 'Bob' };
console.log(array); // [{ name: 'Joe' }, { name: 'Paul' }];
cloneArray[3] = { name: 'Bob' };
console.log(array); // [{ name: 'Joe' }, { name: 'Paul' }, { name: 'Bob'} ];
That's because cloneArray is assigned by reference to array, while spreadArray is assigned to a new array with the same elements as array. That's also why
cloneArray === array; // true
spreadArray === array; // false

Related

How to remove object key value of an object array?

I have an object array with object key value.
arr = [obj1:{name:"Jack", surname:"Peralto"}, obj2:{name:"Husnu", surname:"White"}]
I do not want to see obj1 and obj2 labels. Because of these labels I could not use a word template package.
So I want to convert it to this form.
arr = [{name:"Jack", surname:"Peralto"}, {name:"Husnu", surname:"White"}]
.map function does not work at first array.
arr.map(o=>o)
Why I have an array like this? I should use reduce function and obj1 and obj2 labels are key value when I create object array. Now I don't need them.
When you fix the syntax errors in your code ([obj1:{... is not a valid data structure) you can use Object.values to get at the nested objects.
const obj = {
obj1: {
name: "Jack",
surname: "Peralto"
},
obj2: {
name: "Husnu",
surname: "White"
}
};
console.log(Object.values(obj));
its not the right syntax of array you have used array don't have key value pair
use this syntax if you are using object of objects with key value pair
const obj = {
obj1: {
name: "Jack",
surname: "Peralto"
},
obj2: {
name: "Husnu",
surname: "White"
}
};
or use this an array contains object
arr = [
{name:"Jack", surname:"Peralto"},
{name:"Husnu", surname:"White"}
]

Remove empty object from array of objects

I have an array of objects and a delete function that pass the index as a parameter but fails to remove the empty object. Objects containing properties can be removed. Does anyone know how to fix it? The example code is shown below.
let array = [
{
id: '1',
name: 'sam',
dateOfBirth: '1998-01-01'
},
{
id: '2',
name: 'chris',
dateOfBirth: '1970-01-01'
},
{
id: '3',
name: 'daisy',
dateOfBirth: '2000-01-01'
},
{}
]
// Objects contain properties can be removed but empty object can not be removed.
const deleteItem = (index) => {
return array.splice(index, 1);
};
Use Array.filter to filter out the items which have no properties
let array = [
{id:"1",name:"sam",dateOfBirth:"1998-01-01"},
{id:"2",name:"chris",dateOfBirth:"1970-01-01"},
{id:"3",name:"daisy",dateOfBirth:"2000-01-01"},
{}
]
const filtered = array.filter(e => Object.keys(e).length)
console.log(filtered)
The above works since Object.keys will return an array of the properties of the object. Getting its length property will get the number of items in the array. If the length property is 0, it is coerced to false (see: Falsy values).

JavaScript: How to copying a few keys from a nested object by destructuring

Say I have an object:
myObj = {
name: 'Luke',
age: 12,
height: '163cm',
weight: '60kg',
others: { one: '1', two: '2', three: '3'} // (Edited) Added one more key here :)
};
I want a copy of this object without certain keys to a new object in a way that the output is as below:
newObj = {
name: 'Luke',
age: 12,
one: '1',
two: '2'
};
I have seen examples of destructing but I wanted to know if it is possible with nested objects. Is something like this doable using destructuring or if not what would be the most efficient way to do this.
One way to achieve this with destructure-like syntax would be like this:
const myObj = {
name: 'Luke',
age: 12,
height: '163cm',
weight: '60kg',
others: { one: '1', two: '2', three : '3'}
};
const newObj = {
/* Copy over values from "myObj" to equivalent keys in "newObj" */
name : myObj.name,
age : myObj.age,
/* Spread keys "one" and "two" of the nested "others" object into "newObj" */
...({one, two} = myObj.others, {one, two})
}
console.log(newObj)
For completeness, an iife approach is possible. It works by creating an arrow function that takes as parameters keys you want to keep. In the function body, spread nested objects as desired.
const myObj = {
name: 'Luke',
age: 12,
height: '163cm',
weight: '60kg',
others: { one: '1', two: '2'}
};
const newObj = (
({name, age, others}) => ({name, age, ...others})
)(myObj);
console.log(newObj);
For the object of unknown depth you can try using recursion.
Create a function which takes an object and array of keys to be removed as arguments.
Create a helper(which takes 1 object as parameter) function inside main and create empty object.
Loop through the properties of obj using for..in.
check if key is not present in the array of keys to be removed then
Check if the value is object then call the function recursively
If its not object then add it to the result obj.
At last return the result object.
The code will convert the object of unknown depth to a plain object and you can also remove keys from nested objects.
const myObj = {
name: 'Luke',
age: 12,
height: '163cm',
weight: '60kg',
others: { one: '1', two: '2'}
};
const removed = ['height','weight','one'];
function removeKeys(obj,removed){
const res = {};
function helper(obj){
for(let key in obj){
if(!removed.includes(key)){
if(typeof obj[key] === "object"){
helper(obj[key]);
}
else res[key] = obj[key]
}
}
}
helper(obj)
return res;
}
const res = removeKeys(myObj,removed);
console.log(res)

How to transform an array to an object [duplicate]

This question already has answers here:
How to convert an array of objects to object with key value pairs
(7 answers)
How to convert an array of key-value tuples into an object
(14 answers)
Closed 5 years ago.
I would like to turn this:
let myArray = [ {city: "NY"}, {status: 'full'} ];
to this:
let myObj = { city: "NY", status: 'full' };
while I tried this:
let newObj = {};
for (var i = 0; i < myArray.length; i++) {
(function(x) {
newObj = Object.assign(myArray[i]);
})(i);
}
it assigns the last pair to the object
Spread the array into Object#assign:
const myArray = [ {city: "NY"}, {status: 'full'} ];
const myObj = Object.assign({}, ...myArray);
console.log(myObj);
Note: Assign into an empty object. If you omit the empty object, the 1st element of the original array will be mutated (everything will be merged into it).
You could also use Array.reduce() which will give you more fine grain control:
const myArray = [
{ city: 'NY', color: 'blue', rodents: { small: false, medium: false, large: true } },
{ status: 'full', color: 'red' },
{ sandwich: 'flavourful' },
]
// item is each object in your array
const reduced = myArray.reduce((newObj, item) => {
// existing props will be overwritten by newer object entries in the array
// this example is same as Object.assign spread with right to left precedence,
// until you want more custom logic
Object.keys(item).forEach((key) => { newObj[key] = item[key] })
return newObj
}, {})
console.log(reduced)
// you will see `red` overwrite `blue`
EDIT: after examining this answer after a year, I note that it isn't optimized at all for ability to deep clone or deep merge. I recommend studying those aspects closer and to be careful of copying or breaking references if you are working immutably.
There is no issue with this in the above example because all values are primitives.
I would tend to agree with Ori that your question seems to be about creating an indexed object which isn't usually a good plan, but if its necessary to key your object with numbers you can do it like this:
let newObj = {};
myArray.forEach((val, index) => { newObj[index] = val });
let myArray = [ {city: "NY"}, {status: 'full'} ];
let newObj = myArray.reduce((acc, curr) => {
Object.keys(curr).forEach(val => {
acc[val] = curr[val]
})
return acc
}, {})
console.log(newObj)
This syntax is supported in IE according to caniuse.com

How to convert key-value pair object into an array of values in ES6?

I'm developing a React application where I need to convert a key-value object like this:
{
0: 'John',
1: 'Tim',
2: 'Matt'
};
To an array of just the values like this:
['John', 'Tim', 'Matt']
How do I accomplish this?
const obj = {
0: 'John',
1: 'Tim',
2: 'Matt'
};
const arr = /* ??? */;
You could use Object.values.
The Object.values() method returns an array of a given object's own enumerable property values, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
var object = { 0: 'John', 1: 'Tim', 2: 'Matt' },
array = Object.values(object);
console.log(array);
With ES6, you could use Array.from and use a callback for the values.
var object = { 0: 'John', 1: 'Tim', 2: 'Matt' },
array = Array.from(Object.keys(object), k => object[k]);
console.log(array);
You can make use of Object.values command.
According to the docs.
Object.values() returns an array whose elements are the enumerable
property values found on the object. The ordering of the properties is
the same as that given by looping over the property values of the
object manually
Although it is an ES2017 solution but since you are using react, you can include stage-0 as a preset for babel and access this functionality
var data ={
0: 'John',
1: 'Tim',
2: 'Matt'
};
var newdata = Object.values(data);
console.log(newdata);
there are other methods like Object.keys which gives you all the keys as an array and Object.entries method returns an array of a given object's own enumerable property [key, value] pairs which might also be useful to you
const obj = {
0: 'John',
1: 'Tim',
2: 'Matt'
};
const arr = [];
for(let key in obj){
arr.push(obj[key]);
}
While you have numerical keys and in an order without gaps, you could use Object.assign with an array as target and the given object as source.
var object = { 0: 'John', 1: 'Tim', 2: 'Matt' },
array = Object.assign([], object);
console.log(array);
This is commonly used one:
const obj={
1:'Azamat',
2: 'Kanybek',
3: 'Manas'}
console.log(Object.values(obj))
for key, value pairs:
const arr = [];
for(let key in obj){
arr.push([key,obj[key]])
}
console.log(arr)

Categories