I have an object that contains symbols as keys. How do I do destructuring assignment in this case?
let symbol = Symbol()
let obj = {[symbol]: ''}
let { /* how do I create a variable here, that holds the value of [symbol] property? */ } = obj
I need to know if this possible, I do know the obvious and simple workarounds, but that's not what I am asking.
UPD. Funny enough I knew how to do that but typescript produced errors, and I thought I did something wrong in JS. Here's a fix for typescript users.
Use an alias (see assigning to new variable names):
let symbol = Symbol()
let obj = { [symbol] : 'value'}
let { [symbol]: alias } = obj
console.log(alias)
Use the same syntax for destructuring as for building the object:
let symbol = Symbol()
let obj = {[symbol]: 'foo'}
let { [symbol]: myValue } = obj;
console.log(myValue);
Related
TLDR Edit: I was confusing object destructuring w/ arrays and spread syntax. Below edit does the trick to recursively unpack the nested object.
let nextLevel = Object.values(obj)
return goingDeep(...nextLevel)
Following is the original question, which I'll leave up in case another noob such as myself runs into this, help save them from the downvotes ;p
Attempt to destructure a nested object recursively returns undefined. Putting that aside simply trying to destructure the same object into different variables returns undefined.
Keeping it simple, just assuming a single key:value (object) per layer so no need to iterate.
const container = {container1: {container2 : {container3: {container4: 'core'}}}}
Putting recursion aside for the moment the following results with simply two different destructuring assignments...
const {level1} = container
console.log(level1) // => container1: {container2:{ etc
const {level1_different} = container
console.log(level1_different) // => undefined
this is what I attempted with the recursion
const goingDeep = (obj) => {
if (obj.hasOwnProperty('container4')){
obj.container4 = 'found'
return obj
} else {
// let {nextLevel} = obj /no good
// return goingDeep(nextLevel) /no good
let nextLevel = Object.values(obj)
return goingDeep(...nextLevel)
}
}
originally had the destructuring at the parameter goingDeep = ({obj}) which I have used successfully for arrays so clearly I'm misunderstanding something(s) fundamental to destructuring objects
You are, indeed, misunderstanding how destructing works. If you have an object, destructing lets you create new variables with the same names as the properties in an object.
let obj = {
prop1: 'value1',
prop2: 'value2',
};
let {prop1, prop2, prop3} = obj;
console.log(prop1, prop2, prop3)
let {nextLevel} = obj
Is the same as
let nextLevel = obj.nextLevel;
I think you might be misunderstanding what destructing does.
To be recursive you will need to dynamically search all properties.
const goingDeep = obj => Object.getOwnPropertyNames(obj).reduce(
(prop, result) => result === null ? (obj[prop] === 'core' ? obj : goingDeep(obj[prop])) : result, null
);
Can anyone explain how the why/how the below method of assigning keys in JavaScript works?
a = "b"
c = {[a]: "d"}
return:
Object {b: "d"}
It's the new ES2015 (the EcmaScript spec formally known as ES6) computed property name syntax. It's a shorthand for the someObject[someKey] assignment that you know from ES3/5:
var a = "b"
var c = {[a]: "d"}
is syntactic sugar for:
var a = "b"
var c = {}
c[a] = "d"
Really the use of [] gives an excellent way to use actual value of variable as key/property while creating JavaScript objects.
I'm pretty much statisfied with the above answer and I appreciate it as it allowed me to write this with a little example.
I've executed the code line by line on Node REPL (Node shell).
> var key = "fullName"; // Assignment
undefined
>
> var obj = {key: "Rishikesh Agrawani"} // Here key's value will not be used
undefined
> obj // Inappropriate, which we don't want
{ key: 'Rishikesh Agrawani' }
>
> // Let's fix
undefined
> var obj2 = {[key]: "Rishikesh Agrawani"}
undefined
> obj2
{ fullName: 'Rishikesh Agrawani' }
>
const animalSounds = {cat: 'meow', dog: 'bark'};
const animal = 'lion';
const sound = 'roar';
{...animalSounds, [animal]: sound};
The result will be
{cat: 'meow', dog: 'bark', lion: 'roar'};
Also, only condition to use [] notation for accessing or assigning stuff in objects when we don't yet know what it's going to be until evaluation or runtime.
I want to make an object but I don't know the name of the key until runtime.
Back in the ES5 days:
var myObject = {};
myObject[key] = "bar";
Writing two lines of code is so painful... Ah, ES6 just came along:
var myObject = {[key]:"bar"};
If the value of key equals foo, then both approaches result in:
{foo : "bar"}
As object keys are strings they can contain any kind of characters and special characters. I recently stumbled upon an object which I receive from an API call. This object has '-' in it's key names.
const object = {
"key-with-dash": []
}
Destructuring does not work in this case because key-with-dash is not a valid variable name.
const { key-with-dash } = object;
So one question came to my mind. How am I supposed to destructure the object in such cases? Is it even possible at all?
const data = {
"key-with-dash": ["BAZ"]
}
const {"key-with-dash": foo} = data;
console.log("foo", foo);
Just give it a valid name
let object = { 'key-with-dash': [] }
let {'key-with-dash':y} = object
console.log(y)
// => []
Did you also know you can destructure with variables?
let object = { 'key-with-dash': [] }
let key = 'key-with-dash'
let {[key]:y} = object
console.log(y)
// => []
Hello Fellow Developers,
I have found a break through this error if none of the above work.
Follow this code
<i>const anyVar = yourData["data-example"] </i>
Hope this works for you if you have any questions please make to ask me.
P.S: I know its a old question but I faced a issue so I thought that some people may also face this. So that is why I have posted this.
a simple example, Why does this give an error?
var zipped = [[0,1,2]];
var extracted = {};
var i = 0;
extracted[zipped[i][0]] = { zipped[i][1]: zipped[i][2] }
>>>Uncaught SyntaxError: Unexpected token [(…)
when this is perfectly fine?
extracted[0] = { 1: 2 }
Because Javascript object literal syntax does not allow expressions in key parts. Keys are always literal. That's why you can write this:
{ foo: 'bar' }
And foo is not taken as a variable.
For variable keys, you always have to use this pattern:
var obj = {};
obj[varKey] = value;
That is invalid syntax. A number is syntactically allowed in an object literal. Arbitrary expressions are not.
Instead, you need to create the object, then set the attribute.
var obj = extracted[zipped[i][0]] = {};
obj[ zipped[i][1] ] = zipped[i][2];
Is it possible to do the following in one line in coffeescript?
obj = {}
obj[key] = value
I tried:
obj = { "#{key}": value }
but it does not work.
It was removed from the language
Sorry for being tardy -- if I remember correctly, it was because some
of our other language features depend on having the key known at
compile time. For example, method overrides and super calls in
executable class bodies. We want to know the name of the key so that a
proper super call can be constructed.
Also, it makes it so that you have to closure-wrap objects when used
as expressions (the common case) whenever you have a dynamic key.
Finally, there's already a good syntax for dynamic keys in JavaScript
which is explicit about what you're doing: obj[key] = value.
There's something nice about having the {key: value, key: value} form
be restricted to "pure" identifiers as keys.
(obj = {})[key] = value
will compile to
var obj;
(obj = {})[key] = value;
This is normal javascript. The only benefit you get from coffeescript is that you don't have to pre-declare var s because it does it for you.
For anyone that finds this question in the future, as of CoffeeScript 1.9.1 interpolated object literal keys are once again supported!
The syntax looks like this:
myObject =
a: 1
"#{ 1 + 2 }": 3
See https://github.com/jashkenas/coffeescript/commit/76c076db555c9ac7c325c3b285cd74644a9bf0d2
Depending on how complex your key is you can always use a variable name matching your key and use it to define an object, like this:
myKey = "Some Value"
obj = {myKey}
Which will compile to:
var myKey, obj;
myKey = "Some Value";
obj = {
myKey: myKey
};
So what you end up with is something close to what you seek, but that requires your keys to be valid variable names.
If you're using underscore, you can use the _.object function, which is the inverse of the _.pairs function.
_.pairs({a: 1, b: 'hello'})
//=> [['a', 1], ['b', 'hello']]
_.object([['a', 1], ['b', 'hello']])
//=> {a: 1, b: 'hello'}
So, assuming myKey = 'superkey' and myValue = 100 you could use:
var obj = _.object([[myKey, myValue]]);
//=> obj = {superkey: 100}