请考虑以下代码:
let [circleTranslateX, circleTranslateY, circleScale] = [this.state.pan.x, this.state.pan.y, this.state.scale];
let circleTransform = [
{circleTranslateX},
{circleTranslateY},
{scale: circleScale}
];
以上工作正常,但如果我改变了行:
{circleTranslateX}
要:
{this.state.pan.x}
我收到Unexpected token
错误。为什么这样,如果代码在解构之前应该是等价的?
答案 0 :(得分:3)
{circleTranslateX}
// valid because it could be re-written as:
// {circleTranslateX: circleTranslateX}
{this.state.pan.x}
// would be akin to:
// {this.state.pan.x: this.state.pan.x}
// which isn't valid object initialisation
// because this.state.pan.x isn't a valid
// object key
答案 1 :(得分:2)
这是由于ECMAScript 2015的新对象速记属性声明。如果您想了解有关其工作原理的更多信息,可以查看语言规范。根据{{3}}:
语法
ObjectLiteral : { } { PropertyDefinitionList } { PropertyDefinitionList , }
PropertyDefinitionList
定义为:
PropertyDefinitionList : PropertyDefinition PropertyDefinitionList , PropertyDefinition
PropertyDefinition
是:
PropertyDefinition : IdentifierReference CoverInitializedName PropertyName : AssignmentExpression MethodDefinition
因此,对象文字可以包含属性定义,它们是以下之一: IdentifierReference
(此处相关的那个), CoverInitializedName
, PropertyName : AssignmentExpression
或 MethodDefinition
。
新的速记语法由 IdentifierReference
被定义为 PropertyDefinition
的选项之一的行定义。这意味着属性定义只能是标识符引用,属性名称将是引用的字符串值和属性值,即评估引用的结果,请参阅language specification on Object Initializers, Section 12.2.6,第二段。
当您查看Section 12.2.6.9的定义时会出现问题:
语法
IdentifierReference : Identifier
[...]
Identifier : IdentifierName but not ReservedWord
IdentifierName
只是标识符的名称(变量名称), ReservedWord
是保留关键字。
现在,将此应用于您当前的示例。当您执行{circleTranslateX}
时,它完全有效,因为circleTranslateX
是 Identifier
(您之前会破坏它),因此 {{1 }} 的。这与属性定义的语法匹配且有效。它与:
IdentifierReference
哪个也有效。相反,您的第二个示例{
circleTranslateX: circleTranslateX
}
无效。这是因为{this.state.pan.x}
不是有效的 this.state.pan.x
,因此不是有效的标识符或标识符引用。这意味着它不匹配对象文字的语法,因此无效。它不被引擎视为对象,因此您对对象文字的尝试会导致意外的令牌。它也可以与(如果它甚至被视为一个对象)相比:
IdentifierName
这当然是无效的,因为您不能在属性名称中包含点。
虽然,你可以使用identifiers, Section 12.1允许表达式作为属性名称,如果用方括号括起来的话:
{
this.state.pan.x: this.state.pan.x
}
但是,如果您之前使用数组解构来获取{
[this.state.pan.x]: this.state.pan.x
}
,我真的认为没有意义。