在对象文字中使用不同的属性名称时出现意外的标记

时间:2017-03-04 01:17:20

标签: javascript ecmascript-6

请考虑以下代码:

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错误。为什么这样,如果代码在解构之前应该是等价的?

2 个答案:

答案 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 } ,我真的认为没有意义。

使用ECMAScript 2015 Compute: Property Names进一步阅读。