简体   繁体   English

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

[英]Unexpected token when using different property name in object literal

Consider the following code: 考虑以下代码:

let [circleTranslateX, circleTranslateY, circleScale] = [this.state.pan.x, this.state.pan.y, this.state.scale];

let circleTransform = [
    {circleTranslateX},
    {circleTranslateY},
    {scale: circleScale}
];

The above works fine, but if I change the line: 上面的工作正常,但如果我更改行:

{circleTranslateX}

To: 至:

{this.state.pan.x}

I get an Unexpected token error. 我收到Unexpected token错误。 Why is this so, if the code should be equivalent before destructuring? 如果在销毁之前代码应该等效,为什么会这样呢?

{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

This is due to ECMAScript 2015's new object shorthand property declarations. 这是由于ECMAScript 2015的新对象速记属性声明。 If you want to learn more about how this works, you can look at the language specification. 如果您想了解更多有关其工作原理的信息,可以查看语言规范。 Per the language specification on Object Initializers, Section 12.2.6 : 根据对象初始化程序语言规范,第12.2.6节

Syntax 句法

 ObjectLiteral : { } { PropertyDefinitionList } { PropertyDefinitionList , } 

Where PropertyDefinitionList is defined as: 其中PropertyDefinitionList定义为:

 PropertyDefinitionList : PropertyDefinition PropertyDefinitionList , PropertyDefinition 

And PropertyDefinition is: PropertyDefinition是:

 PropertyDefinition : IdentifierReference CoverInitializedName PropertyName : AssignmentExpression MethodDefinition 

Thus, an object literal can contain property definitions, which are one of: IdentifierReference (the one that is relevant here), CoverInitializedName , PropertyName : AssignmentExpression , or MethodDefinition . 因此,对象文字可以包含以下属性定义之一: IdentifierReference (此处相关), CoverInitializedNamePropertyName : AssignmentExpressionMethodDefinition

The new shorthand syntax is defined by the line where IdentifierReference is defined as one of the options for a PropertyDefinition . 新的速记语法由IdentifierReference定义为PropertyDefinition的选项之一的行定义。 That means a property definition can just be an identifier reference and the property name will be string value of the reference and the property value, the result of evaluating the reference, see Section 12.2.6.9 , second paragraph. 这意味着属性定义只能是标识符引用,而属性名称将是引用的字符串值和属性值,即对引用进行评估的结果,请参见第12.2.6.9节 ,第二段。

The problem comes in when you look at the definition of identifiers, Section 12.1 : 当您查看标识符的定义,第12.1节时,就会出现问题:

Syntax 句法

 IdentifierReference : Identifier 

[...] [...]

 Identifier : IdentifierName but not ReservedWord 

Where IdentifierName is just the identifier's name (variables name) and ReservedWord is a reserved keyword. 其中IdentifierName仅是标识符的名称(变量名称),而ReservedWord是保留的关键字。

Now, to apply this to your current example. 现在,将其应用于当前示例。 When you do {circleTranslateX} , it's perfectly valid because circleTranslateX is an Identifier (you destruct it earlier) and thus IdentifierReference . 当您执行{circleTranslateX} ,它是完全有效的,因为circleTranslateX是一个Identifier (您之前circleTranslateX进行了销毁),因此也是IdentifierReference This matches the syntax for a property definition and is valid. 这与属性定义的语法匹配,并且有效。 It's comparable to: 相当于:

{
    circleTranslateX: circleTranslateX
}

Which is also valid. 这也是有效的。 On the contrary, your second example {this.state.pan.x} is invalid. 相反,您的第二个示例{this.state.pan.x}无效。 This is because this.state.pan.x is not a valid IdentifierName , thus not a valid identifier or identifier reference. 这是因为this.state.pan.x不是有效的IdentifierName ,因此不是有效的标识符或标识符引用。 That means it does not match the syntax for an object literal and is thus invalid. 这意味着它与对象文字的语法匹配,因此无效。 It's not seen as an object by the engine so your attempt at an object literal results in an unexpected token. 引擎未将其视为对象,因此您尝试使用对象文字会导致意外的令牌。 It's also comparable to (if it were even treated as an object): 它也可与(甚至被视为对象)进行比较:

{
    this.state.pan.x: this.state.pan.x
}

This is of course invalid because you can't have dots in property names. 这当然是无效的,因为属性名称中不能包含点。

Although, you could use ECMAScript 2015 Compute: Property Names which allow for expressions as property names if enclosed in square brackets: 虽然,您可以使用ECMAScript 2015 Compute:属性名称 ,如果用方括号括起来,则允许将表达式作为属性名称使用:

{
    [this.state.pan.x]: this.state.pan.x
}

But I really see no point if you use array destructuring earlier to get circleTranslateX . 但是我真的看不到如果您之前使用数组结构circleTranslateX来获取circleTranslateX是没有circleTranslateX

Further reading with Object Initializers at MDN . 使用MDN的对象初始化器进一步阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM