Reputation: 36703
I have a different use case in which when using the concept of destructuring I want the name of new variable to come from different variables.
For ex (usual destructuring):
var o = {p: 42, q: true};
var {p: foo, q: bar} = o;
console.log(foo, bar); // Works fine
Is working fine but when I try to replace p, foo, q, bar
with some other variable I get the error because I can not get the syntax right.
The closest I have reached is:
var o = {p: 42, q: true};
var x1 = "p";
var x2 = "foo";
var x3 = "q";
var x4 = "bar";
var {[x1]: foo, [x3]: bar} = o;
console.log(foo, bar);
Othe things which I tried but didnt work are:
var {[x1]: window[x2], [x3]: bar} = o; //Uncaught SyntaxError: Unexpected token [
var {[x1]: (()=>x2)(), q: bar} = o; //Uncaught SyntaxError: Unexpected token (
But here I am still not able to replace foo, bar
with x2, x4
.
Any idea how can one achieve this? Or is it even possible to do this?
Upvotes: 4
Views: 234
Reputation: 239573
It was answered perfectly in this comment. I'll try to explain with the specification details.
When we declare a variable, like this
var {[x1]: window[x2], [x3]: window[x4]} = o;
I removed all the subscripted text from the spec for brevity
it would follow the following production as per Variable Statement Section,
VariableStatement:
var VariableDeclarationList;
VariableDeclarationList:
VariableDeclaration
VariableDeclarationList, VariableDeclaration
VariableDeclaration:
BindingIdentifier Initializer
BindingPattern Initializer
As {[x1]: window[x2], [x3]: window[x4]}
is not a BindingIdentifier
, it is a BindingPattern
. And that production goes like this
BindingPattern:
ObjectBindingPattern
ArrayBindingPattern
ObjectBindingPattern:
{}
{BindingRestProperty}
{BindingPropertyList}
{BindingPropertyList, BindingRestProperty}
...
...
BindingPropertyList:
BindingProperty
BindingPropertyList, BindingProperty
...
...
BindingProperty:
SingleNameBinding
PropertyName: BindingElement
BindingElement:
SingleNameBinding
BindingPattern Initializer
SingleNameBinding:
BindingIdentifier Initializer
In this case ({[x1]: window[x2], [x3]: window[x4]}
), the production goes like this BindingPattern
-> ObjectBindingPattern
-> {BindingPropertyList}
-> BindingProperty
-> PropertyName: BindingElement
-> SingleNameBinding
-> BindingIdentifier
.
At this point, window[x2]
is not a BindingIdentifier
. That is why you are getting the SyntaxError
, Uncaught SyntaxError: Unexpected token [
.
But it works in case of ({[x1]: window[x2], [x3]: window[x4]} = o)
because, it is not a variable declaration anymore. It is a destructuring assignment.
Production for that goes like this
AssignmentPattern:
ObjectAssignmentPattern
ArrayAssignmentPattern
ObjectAssignmentPattern:
{}
{AssignmentRestProperty}
{AssignmentPropertyList}
{AssignmentPropertyList, AssignmentRestProperty}
AssignmentPropertyList:
AssignmentProperty
AssignmentPropertyList, AssignmentProperty
AssignmentProperty:
IdentifierReference Initializer
PropertyName: AssignmentElement
AssignmentElement:
DestructuringAssignmentTarget Initializer
DestructuringAssignmentTarget:
LeftHandSideExpression
LeftHandSideExpression:
NewExpression
CallExpression
CallExpression:
CoverCallExpressionAndAsyncArrowHead
SuperCall
CallExpression Arguments
CallExpression[Expression]
CallExpression.IdentifierName
CallExpression TemplateLiteral
Here the production is complete with CallExpression[Expression]
. That is why ({[x1]: window[x2], [x3]: window[x4]} = o)
is valid and it is working.
Upvotes: 1
Reputation: 5193
You need an lvalue to assign to, but from what i know, you cannot declare dynamically generated variable names, as in let [dynamicName] = value
. However, object properties are an alternative, which can dynamically be generated:
var o = {p: 42, q: true};
var container = {};
var x1 = "p";
var x2 = "foo";
var x3 = "q";
var x4 = "bar";
({[x1]: container[x2], [x3]: container[x4]} = o);
console.log(container.foo, container.bar);
On global scope, you can abuse the fact that the global object is being used as object environment, and use window[x2]
and window[x4]
, but it's not really useful in production code.
Upvotes: 2