简体   繁体   中英

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. 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. 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 :

Syntax

 ObjectLiteral : { } { PropertyDefinitionList } { PropertyDefinitionList , } 

Where PropertyDefinitionList is defined as:

 PropertyDefinitionList : PropertyDefinition PropertyDefinitionList , PropertyDefinition 

And PropertyDefinition is:

 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 .

The new shorthand syntax is defined by the line where IdentifierReference is defined as one of the options for a 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.

The problem comes in when you look at the definition of identifiers, Section 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.

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 . 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 is because this.state.pan.x is not a valid IdentifierName , thus not a valid identifier or identifier reference. 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:

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

But I really see no point if you use array destructuring earlier to get circleTranslateX .

Further reading with Object Initializers at MDN .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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