I was reading key interpolation in javascript and the article, it says following is a key interpolation
const example = {key1: value1, key2: value2}
and to add new value to the above object we will do the following
const example1 = {...example, [key3]:value3}
and this gives o/p as:
{key1: value1, key2: value2,key3: value3}
The article says bracket is required for key interpolation.
I tried the same things as
const example1 = {...example, key3:value3}
and it gives the same result.
Is there any difference between them or they are the same as they give the same o/p?
it says following is a key interpolation const example = {key1: value1, key2: value2}
I don't see any "key interpolation" there.
...and to add new value to the above object we will do the following const example1 = {...example, [key3]:value3} and this gives o/p as {key1: value1, key2: value2,key3: value3}.
Only if you have a variable called key3 which has the value "key3" in it, which seems like a really confusing example for an article to have.
The article says bracket is required for key interpolation.
I tried the same things as const example1 = {...example, key3:value3} and it gives the same result. Is there any difference between them or they are the same as they give the same o/p?
The difference is whether you're providing the name of the property (the key) using literal notation (no []) or computed notation (with []):
// Literal notation, adds a property called `key` to the object
const obj1 = {key: "value"};
console.log(obj1.key); // "value"
// Computed notation, adds a property whose name comes from the
// contents of the variable `key` to the object:
const key = "propertyName";
const obj2 = {[key]: "value"};
console.log(obj2.key); // undefined, there isn't any property with the name "key"
console.log(obj2.propertyName); // "value"
console.log(obj2[key]); // "value"
They are not the same.
If you use string literals, then they behave the same.
These are identical:
const example1 = {foo: 'bar'}
const example2 = {'foo': 'bar'}
const example3 = {['foo']: 'bar'}
The difference appears when you try to put an expression in a key:
const keyName = 'foo'
const example1 = {keyName: 'bar'} //{keyName: 'bar'}
const example2 = {[keyName]: 'bar'} //{foo: 'bar'}
The interpolator syntax ([]) allows you to put any expression into the key, for example, this is also valid:
const fn = foo => foo.length
const example = {
[10 - fn('baz') + 'baz']: 'bar'
}
//{7baz: 'bar'}
Related
I have multiples URLSearchParams created from object mainly because it's lighter to write and to read but for some of them, I need multiple values for a "variable" like this : foo=bar&foo=baz.
For now I do it with .append but it's heavy to read having multiple lines pretty identical.
Is there a way to do it from the constructor, with an object ?
let params;
// Currently used (and working) code
params = new URLSearchParams()
params.append("foo", "bar");
params.append("foo", "baz");
console.log(params.toString()); //Wanted result but heavy to read with more values
// Wanted code (but not the wanted result for now)
params = new URLSearchParams({
"foo": ["bar", "baz"]
});
console.log(params.toString());
params = new URLSearchParams({
"foo": "bar",
"foo": "baz"
});
console.log(params.toString());
The URLSearchParams can takes an init value as argument for its constructor containing the following:
One of:
A string, which will be parsed from application/x-www-form-urlencoded format. A leading '?' character
is ignored.
A literal sequence of name-value string pairs, or any object — such as a FormData object — with an iterator that produces a sequence of
string pairs. Note that File entries will be serialized as [object File] rather than as their filename (as they would in an
application/x-www-form-urlencoded form).
A record of string keys and string values.
In your case the second one seems to work the best and can be done like this:
const searchParams = new URLSearchParams([['foo', 'bar'],['foo', 'baz'],['foo', 'qux']])
console.log(searchParams.toString())
If you want to deal with objects, you can create your own structure and use a function to create the wanted data
For example :
const params = [
{name: "foo", values: ["bar", "baz", "qux"]},
{name: "bar", values: ["foo", "foo2", "foo3"]},
]
const initParams = (params) => params.reduce((acc, curr) => {
const arr = curr.values.map(x => [curr.name, x])
return acc.concat(arr)
}, [])
const searchParams = new URLSearchParams(initParams(params))
console.log(searchParams.toString())
I would introduce a function to build the thing you need (URLSearchParams) from the structure you want (an object containing strings or arrays of strings), pushing the "heavy" details down below an interface you own. A simple implementation would just use .append as appropriate:
// For TypeScript (e.g. Angular) users:
// function createSearchParams(params: { [key: string]: string | string[] }): URLSearchParams {
function createSearchParams(params) {
const searchParams = new URLSearchParams();
Object.entries(params).forEach(([key, values]) => {
if (Array.isArray(values)) {
values.forEach((value) => {
searchParams.append(key, value);
});
} else {
searchParams.append(key, values);
}
});
return searchParams;
}
console.log(createSearchParams({
foo: ["bar", "baz"],
hello: "world",
}).toString());
This provides an abstraction, so if you decide you'd rather use the init approach under the hood, you can do so, e.g.:
function createSearchParams(params) {
return new URLSearchParams(Object.entries(params).flatMap(([key, values]) => Array.isArray(values) ? values.map((value) => [key, value]) : [[key, values]]));
}
console.log(createSearchParams({
foo: ["bar", "baz"],
hello: "world",
}).toString());
All of your tests will continue to pass, you don't have to change the consuming code. This is much neater than defining a function to convert the structure you want to the thing URLSearchParams needs, as shown in RenaudC5's answer.
console.log('' + new URLSearchParams(['bar', 'baz', 'qux'].map(v=>['foo', v])))
I have an Javascript object called person with various properties such as id, name, phone, etc.
I want to create a new Javascript object called roster that is just the name. Something like this:
let person = { name: "Hilda", "id": 123, "phone": 000-000-0000 };
let roster = { person.name : person.phone };
However, React throws an error having person.name in the key. It doesn't matter if I do person.name or person["name"]. I have to do:
let roster = {};
roster[person.name] = person.phone;
Is there some special syntax to allow person.name to be set as the key directly, or is the work-around required?
Use []
let person = { name: "Hilda", "id": 123, "phone": "000-000-0000" };
let roster = { [person.name] : person.phone };
console.log(roster)
Vugar's answer is correct, this can be done by placing brackets [] around the first object's property name.
This is called a computed property name. From the MDN web docs:
The object initializer syntax also supports computed property names.
That allows you to put an expression in brackets [], that will be
computed and used as the property name. This is reminiscent of the
bracket notation of the property accessor syntax, which you may have
used to read and set properties already.
Now you can use a similar syntax in object literals, too:
// Computed property names
let i = 0;
const a = {
[`foo${++i}`]: i,
[`foo${++i}`]: i,
[`foo${++i}`]: i,
};
console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3
const items = ["A", "B", "C"];
const obj = {
[items]: "Hello",
};
console.log(obj); // A,B,C: "Hello"
console.log(obj["A,B,C"]); // "Hello"
const param = 'size';
const config = {
[param]: 12,
[`mobile${param.charAt(0).toUpperCase()}${param.slice(1)}`]: 4,
};
console.log(config); // {size: 12, mobileSize: 4}
MDN Docs Reference
Say I have an object with some properties:
const obj = {
key1: 1
key2: 2
}
and I have a function someFunc that takes one object as a parameter. I want to pass obj with some additional parameters, like
someFunc({
key1: 1
key2: 2
otherKey: 3
})
The problem is that I don't want to actually change the state of obj. After someFunc has been called it should not contain otherKey as a property.
This leaves Object.assign out of the question:
let ident = someObj => someObj;
ident(Object.assign(obj, {otherKey: 3}))
console.log(someObj); // -> {key1: 1, key2: 2, otherKey: 3}
Creating a new variable and assigning otherKey = 3 to it does the same thing.
I know I can use some sort of deep duplication - but that seems like an unnecessarily complex way of handling a fairly simple problem.
The most elegant way of doing this would be a pure function that takes some objects obj1, obj2, returns the same output as Object.assign(obj1, obj2), but alters neither of them. Is there some obvious way of doing this in JS that I haven't seen, or do I have to use some other library?
Just reverse the parameters to Object.assign - it will add the properties from obj to a new object:
ident(Object.assign({otherKey: 3}, obj))
Caution
But you must be careful about properties that are already present in obj as they will overwrite the ones in the new array.
You are dealing with immutability. Another way to accomplish thit is to use spread operator of ES6:
const obj1 = {
key1: 1,
key2: 2,
}
const obj2 = {
key1: 1,
key2: 12,
otherKey: 3
};
const merged = { ...obj1, ...obj2 };
console.log('merged: ', merged);
console.log('obj1: ', obj1);
console.log('obj2: ', obj2);
You'll see that neither obj1 nor obj2 is altered
I've been experimenting with concepts of immutability with javascript objects. I was wondering if the following code example implements what I believe is known as "Structural Sharing" (see: https://www.youtube.com/watch?v=e-5obm1G_FY&start=1123).
const objectFirst = {
key1: 1,
key2: 2
}
const updateObject = (lastObject) => {
const updatedObject = {...lastObject, ...{ key2: 4 }} // Object.assign({}, lastObject, { key2: 4 })
return updatedObject
}
const objectNext = updateObject(objectFirst)
objectNext is now { key1: 1, Key2: 4 } and objectFirst is unchanged. But has key1 been duplicated? Or, is their now essentially a reference to key1's location in memory shared by both objects?
I'm basically just asking if this approach implements some sort of "Structural Sharing"? One could see that if this were not the case, then it would lead to significant memory bloat.
No, because 1 is stored as a simple value on objectFirst, not a reference to an object, so when you do {...objectFirst} you're copying the value of objectFirst.key1 to objectNext.key1.
However, if objectFirst.key1 was an object instead, then the shallow copy would copy the object reference instead of creating a new object. As a result, objectFirst.key1 and objectNext.key2 would both reference the same object.
const objectFirst = {
key1: 1,
key2: 2,
sharedObject: {foo: 'original string'}
}
// we make a shallow copy with a different key2 value.
const objectSecond = {...objectFirst, key2: 4};
// changing a value in objectSecond doesn't affect objectFirst
objectSecond.key1 = 100;
console.log(objectFirst.key1); // 1
// but sharedObject is shared
objectSecond.sharedObject.foo = "new string";
console.log(objectFirst.sharedObject); // {foo: "new string"}
console.log(objectFirst['key1'] === objectNext['key1']); // true
console.log(objectFirst['key2'] === objectNext['key2']); // false
This means objectFirst and objectNext share the key1 property.
I am able to have an object like this
var obj = {key1: value1, key2: value2};
but i need an object having multiple value how can i achieve it?
for example
var obj = {key1:{ value1,value2}, key2: {value3,value4,value5}};
An object can have properties. And the property is implementation of key value pair in javascript. If you want to have keys in an object, you need to put value for each key.
In example of yours,
var obj = {key1:{ value1,value2}, key2: {value3,value4,value5}};
sholud be
var obj = {
key1:{ value1:null, value2:null },
key2: {value3:null, value4: null, value5: null}
};
so that, you can the directly access key in obj like obj.key1.value1 Additionally you can get keys Object.keys(obj); => ['key1', 'key2'] and Object.keys(obj.key1); => ['value1', 'value2']