Does the placement/order of spreading in an object matter? - javascript

In JavaScript does the placement and ordering when using spread syntax matter?
var item = {/* key value pairs here */};
var itemB = {/* key value pairs here */};
For example in the following code snippets will newItem always have the same key value pairs?
var newItem = {
...item,
...itemB
};
as
var newItem = {
...itemB,
...item
};

Besides just the general order of the key value pairs, which doesn't really have a super major impact on the result of the object, the only other difference would be if item and itemB have duplicate keys.
For example.
var item = {firstName: "Bob"};
var itemB = {lastName: "Smith", firstName: "Tim"};
In this case the following two items will not be identical.
var newItem = {
...item,
...itemB
};
// {lastName: "Smith", firstName: "Tim"}
var newItem = {
...itemB,
...item
};
// {lastName: "Smith", firstName: "Bob"}
So if there are duplicate keys, the order of the objects being spread does matter.
This can be especially useful if you wish to provide default key value pairs for an object. You can just put the default key value pairs first and it will act as defaults for the new object if they don't exist in the object that is being used with the spread syntax.

Related

how to concatenate two object and replace the values?

I'm trying to concatenate two objects. I need to merge the two object and based on the "beforeVist" object value within the arrow.
My two objects down below:
const beforeVist = {
name : '<<name>>',
age : '<<age>>',
place : '<<place>>'
};
const afterVist = {
name : 'Robin',
age : 22,
place : 'Mars'
}
var Updated = {...afterVist, ...beforeVist};
console.log(Updated)
when I'm trying do console.log() function output below,
{
name : 'Robin',
age : 22,
place : 'Mars'
}
this is what my expected output is. I'm not sure that it is the right way.
Thanks advance!!!
You could also use Object.assign
const a = {p1: 12, p2: 23}
const b = {p2: 34, p3: 'adfa'}
let c = Object.assign(b, a)
// c contains:
{p2: 23, p3: "adfa", p1: 12}
If you care about immutability, you can provide separate "result" object:
const res = Object.assign({}, b, a)
// a and b still hold the original values
NOTE: properties ORDER will be driven from left-to-right ("p2" is the first prop in B, but second in A), but the VALUES from right-to-left(result.p2 contains value from the rightMost object with such property - ie A.p2 overrides B.p2
It is the right way. You should use object sprad
let merged = {...obj1, ...obj2};
Method for ES5 and Earlier
for (var attrname in obj2) { obj1[attrname] = obj2[attrname]; }
Because << >> are always at the first two places and the last two places we can simply slice and then reassign the value.
const beforeVist = {
name: '<<name>>',
age: '<<age>>',
place: '<<place>>'
};
const afterVist = {
name: '<<Robin>>',
age: '<<22>>',
place: '<<Mars>>'
}
var Updated = {...beforeVist, ...afterVist };
Object.entries(Updated).forEach(([key, value]) => {
let val = value.slice(2, value.length - 2);
Updated[key] = val;
})
console.log(Updated)
At the moment you are just overwriting the properties from afterVist with the properties in beforeVist, and since the property names are the same, you're essentially just making a shallow copy. This is more evident if your afterVist has different property names to beforeVist (and why I've provided different property names in beforeVist below - to show that they don't have to be the same and that the value is grabbed based on the key specified in <<key>>)
Instead, you can use Object.fromEntries() by mapping the Object.entries() of your original object, and using replace on the keys to extract the key name like so:
const beforeVist = { myName: '<<name>>', myAge: '<<age>>', myPlace: '<<place>>' };
const afterVist = { name: 'Robin', age: 22, place: 'Mars' };
const result = Object.fromEntries(Object.entries(beforeVist).map(([key, value]) => [
key,
value.replace(/<<([^>>]*)>>/, (_, g) => afterVist[g])
]));
console.log(result);

How do you convert an object with duplicate keys to JSON/String?

Imagine you have an object like this:
var obj = {
name: "Mike",
name: "George",
age: 24,
}
Converting this to JSON with JSON.stringify(obj) yields:
{"name":"George","age":24}
This causes loss of data and isn't something we want.
Converting this to a string with toString() yields
[object Object]
, which isn't what we want either.
How does one go about this?
PS: I am aware that objects can't have two identical keys.
So after some brainstorming with the nice users that have commented here, a simple way to deal with this is to just turn it into a string manually. Like this:
var obj = `
name: "Mike",
name: "George",
age: 24,
`;
Then just parse it to your heart's content. For me personally, this could be a way to do it. However, this will obviously depend on the user-case.
var obj2 = {};
str = str.split(",").map(e => e.replace(/(\")/gi, "").trim());
str.forEach((e, i) => {
var temp = e.slice(0, e.indexOf(":"));
if(obj2[temp]) obj2[temp].push(e.slice(e.indexOf(":") + 1).trim());
else obj2[e.slice(0, e.indexOf(":"))] = [e.slice(e.indexOf(":") + 1).trim()];
})
The code above just splits the string based on some desired separator and processes the given array further. This might be a indelicate way to solve the question, but it works for my scenario :/. It yields the following JSON-object:
{"name":["Mike","George"],"age":["24"]}
Right after your object is defined, the second "name" key will override the first "name" key.
You can re-structure your object like this:
var obj = {
name: ["Mike","George"],
age: 24,
}
or
var arrayObj = [{
name: "Mike",
age: 24,
},{
name: "George",
age: 24,
}]
and use the built-in function for string in js to get your expected result.
Hope this helps!
You can't do it. the "name" value is the second value assigned to "name" key in javascript object or JSON. try to use obj.name it will be "George"
This is workaround to do what are you need.you can use "_" or any unused symbol.
const obj = {
name: 'ahmed',
_name: 'elmetwally',
title: 'js dev',
};
console.log(JSON.stringify(obj).replace(/\_/g, ''));
Here's a simple method to convert a string representation of the object into an array of key-value pairs.
It's not a general method, but it should work fine for an object with no nesting.
let result = document.getElementById('result');
let jsonStr = `{ name: "Mike", name: "George", age: 24 }`;
result.innerHTML = `jsonStr: "${jsonStr}"\n`;
// strip out '{}'
let jsonClean = jsonStr.replace(/{/g, '').replace(/}/g, '');
result.innerHTML += `jsonClean: "${jsonClean}"\n`;
// split jsonClean into array of key-value strings
let kvStrings = jsonClean.split(',');
result.innerHTML +=
`kvStrings: ${JSON.stringify(kvStrings)}\n`;
// form array of key-value pairs
let kvPairs = kvStrings.map(kvstr => {
let [key, value] = kvstr.split(':').map(el => el.trim());
// strip double quotes or convert to number
if (value.includes('"')) {
value = value.replace(/"/g, '');
} else {
value = Number.parseFloat(value);
}
return [key, value];
});
result.innerHTML += `kvPairs: ${JSON.stringify(kvPairs)}`;
<pre id="result"></pre>
So after some brainstorming with the nice users that have commented here, a simple way to deal with this is to just turn it into a string manually. Like this:
var obj = `
name: "Mike",
name: "George",
age: 24,
`;
Then just parse it to your heart's content. For me personally, this could be a way to do it. However, this will obviously depend on the user-case.
var obj2 = {};
str = str.split(",").map(e => e.replace(/(\")/gi, "").trim());
str.forEach((e, i) => {
var temp = e.slice(0, e.indexOf(":"));
if(obj2[temp]) obj2[temp].push(e.slice(e.indexOf(":") + 1).trim());
else obj2[e.slice(0, e.indexOf(":"))] = [e.slice(e.indexOf(":") + 1).trim()];
})
The code above just splits the string based on some desired separator and processes the given array further. This might be a indelicate way to solve the question, but it works for my scenario :/. It yields the following JSON-object:
{"name":["Mike","George"],"age":["24"]}

How to create an array of objects with key/value pairs from selector variables in $each function?

I am trying to create a new object in jquery with the values of multiple selectors. For example:
loopSelector = $('.myClass');
loopSelector.each(function(i, elem) {
var1 = $(elem).parents('li').text();
var2 = $(elem).parents('p').text();
var newArray = [{
animal: var1
age: var2
}];
console.log(newArray);
}
In the console I get:
Array(1)
0: {animal: 'cat', age: 12}
Array(1)
0: {animal: 'dog', age: 5}
Array(1)
0: {animal: 'goat', age: 7}
But when I try to console.log(newArray.age); I get undefined 3 times. My goal is to compare all of the objects by the value of age.
Is there a better way of doing this?
Since you want to create an array of the same elements selected, just with a different data representation for each, consider using .map() instead of .each():
loopSelector = $('.myClass');
var array = loopSelector.map(function (i, elem) {
var animal = $(elem).parents('li').text();
var age = $(elem).parents('p').text();
return {
animal: animal,
age: age
};
}).get();
console.log(array);
Note the use of .get() at the end (as pointed out by Taplar in the comments), which converts the jQuery object into a regular Javascript array.
Or with some fancy ES6 features thrown in to tidy things up a little:
const array = $('.myClass').map((i, elem) => {
const animal = $(elem).parents('li').text();
const age = $(elem).parents('p').text();
return { animal, age };
}).get();
console.log(array);
You can try the below code snippet to access object directly:
loopSelector = $('.myClass');
var newArray = [];
loopSelector.each(function(i, elem) {
var obj = {};
var1 = $(elem).parents('li').text();
var2 = $(elem).parents('p').text();
obj.animal = var1;
obj.age = var2;
newArray.push(obj);
}
newArray.map(val => {
//Here your will be able to access directly to objects with key name.
console.log(val)
});

storing key value pairs in an array in javascript

I have 2 arrays namely,
configdata = ["assignee", "shortDesc"];
ticketarray = ["Tom","testDesc"];
I want to store the values as a key value pair in another array, something like this:
ticketData = ["assignee":"Tom","shortDesc":"testDesc"];
Kindly note that the array values are dynamic, so I cannot hardcode them.
Is there a way to do so? I am able to achieve the above said requirement but the length always shows 0. This is the code that I am using:
configdata.Incident_Field.forEach(function (k, i) {
this[k] = ticketarray[i];
}, ticketData);
Other people have explained why your code did not work. I am providing another solution using reduce.
const configdata = ["assignee", "shortDesc"];
const ticketarray = ["Tom", "testDesc"];
let ticketData = configdata.reduce((result, value, index) => {
result[value] = ticketarray[index];
return result;
}, {});
console.log(ticketData);
Output:
{
assignee: "Tom",
shortDesc: "testDesc"
}
The below is not a valid structure in JavaScript:
ticketData = ["assignee":"Tom","shortDesc":"testDesc"];
What you need is a JavaScript object. The best you can do is:
Make sure both the array lengths are same.
Associate the key and value by creating a new object.
Use Object.keys(obj).length to determine the length.
Start with the following code:
configdata = ["assignee", "shortDesc"];
ticketarray = ["Tom", "testDesc"];
if (configdata.length == ticketarray.length) {
var obj = {};
for (var i = 0; i < configdata.length; i++)
obj[configdata[i]] = ticketarray[i];
}
console.log("Final Object");
console.log(obj);
console.log("Object's Length: " + Object.keys(obj).length);
The above will give you an object of what you liked, a single variable with all the values:
{
"assignee": "Tom",
"shortDesc": "testDesc"
}

return object via array values

I have an object and would like to find and return the object values based on an array.
var profile = {
'firstName' : 'John',
'lastName' : 'Doe',
'mood' : 'happy'
};
var updated= ['firstName','mood'];
The updated array gets changed with the key when a the relevant field has been changed.
Thanks.
I have an object and would like to find and return the object values based on an array.
You don't need underscore.js for this. You can do this with plain js simply by iterating over the array and extracting the necessary properties from your object:
var profile = {
'firstName': 'John',
'lastName': 'Doe',
'mood': 'happy'
};
var updated = ['firstName', 'mood'];
updated.forEach(function(prop) {
console.log(profile[prop]);
});
The updated array gets changed with the key when a the relevant field has been changed.
Not sure I understand you exactly, but it seems that you want an array of values for properties of the profile object whose names are contained in the updated array. Using Array.prototype.map would do the trick:
var profile = {
'firstName': 'John',
'lastName': 'Doe',
'mood': 'happy'
};
var updated = ['firstName', 'mood'];
var values = updated.map(function(prop) {
return profile[prop];
});
console.log(values);
Seeing that you asked for an underscore solution, here's one:
Pick returns an object with just the keys that you want:
var result = _.pick(profile, updated);
So result will look like:
{
'firstName' : 'John',
'mood' : 'happy'
}
If you need just the values in an array then use the values function:
var values = _.values(result);

Categories

Resources