我有一个不同的用例,其中在使用解构概念时,我希望新变量的名称来自不同的变量。
对于前(通常为解构):
var o = {p: 42, q: true};
var {p: foo, q: bar} = o;
console.log(foo, bar); // Works fine
工作正常,但是当我尝试用其他变量替换p, foo, q, bar
时出现错误,因为语法不正确。
最接近的是:
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);
我尝试但没有奏效的事情是:
var {[x1]: window[x2], [x3]: bar} = o; //Uncaught SyntaxError: Unexpected token [
var {[x1]: (()=>x2)(), q: bar} = o; //Uncaught SyntaxError: Unexpected token (
但是在这里,我仍然无法将foo, bar
替换为x2, x4
。
有人知道如何实现这一目标吗?还是有可能这样做?
答案 0 :(得分:2)
您需要分配一个左值,但是据我所知,您不能像let [dynamicName] = value
那样声明动态生成的变量名。但是,对象属性是一种替代方法,可以动态生成:
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);
在全局范围内,您可以滥用将全局对象用作对象环境这一事实,并使用window[x2]
和window[x4]
,但这在生产代码中并不是真正有用的。
答案 1 :(得分:1)
in this comment得到了很好的回答。我会尝试用规格说明来解释。
当我们声明一个变量时,就像这样
var {[x1]: window[x2], [x3]: window[x4]} = o;
为了简洁起见,我从规范中删除了所有下标文字
它将按照Variable Statement Section进行以下生产,
VariableStatement:
var VariableDeclarationList;
VariableDeclarationList:
VariableDeclaration
VariableDeclarationList, VariableDeclaration
VariableDeclaration:
BindingIdentifier Initializer
BindingPattern Initializer
由于{[x1]: window[x2], [x3]: window[x4]}
不是BindingIdentifier
,所以它是BindingPattern
。那生产就像这样
BindingPattern:
ObjectBindingPattern
ArrayBindingPattern
ObjectBindingPattern:
{}
{BindingRestProperty}
{BindingPropertyList}
{BindingPropertyList, BindingRestProperty}
...
...
BindingPropertyList:
BindingProperty
BindingPropertyList, BindingProperty
...
...
BindingProperty:
SingleNameBinding
PropertyName: BindingElement
BindingElement:
SingleNameBinding
BindingPattern Initializer
SingleNameBinding:
BindingIdentifier Initializer
在这种情况下({[x1]: window[x2], [x3]: window[x4]}
,生产像这样BindingPattern
-> ObjectBindingPattern
-> {BindingPropertyList}
-> BindingProperty
-> {{1 }}-> PropertyName: BindingElement
-> SingleNameBinding
。
在这一点上,BindingIdentifier
不是window[x2]
。这就是为什么您得到BindingIdentifier
,SyntaxError
的原因。
但是它在Uncaught SyntaxError: Unexpected token [
的情况下有效,因为它不再是变量声明。这是destructuring assignment。
为此生产
({[x1]: window[x2], [x3]: window[x4]} = o)
此处的制作已完成,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
。这就是CallExpression[Expression]
有效且有效的原因。