【问题标题】:shorthand property name with *this*带有 *this* 的简写属性名称
【发布时间】:2018-04-19 08:56:40
【问题描述】:

以下代码失败

let x = {this}

为什么我不能在 this 中使用速记属性名称?


来自浏览器的错误消息

chrome 66.0.3359.117 : Uncaught SyntaxError: Unexpected token }

firefox 59.0.1:这是一个无效的标识符

edge 41.16299.371.0 : 对标识符使用关键字是无效的

我不太明白这些消息的含义。


为了说明清楚,下面的代码运行良好

let x = 5
let y = {x}
let z = {this:this}

console.log({x,y,z})

【问题讨论】:

  • 因为this是一个关键字,像function、if、for等等……如果你加值,那么它就变成了一个key。
  • 不确定,但似乎{} 创建了一个对象字面量,而内部对象this 总是引用它自己的对象,此处未定义
  • @RadonirinaMaminiaina 我不能使用 function if for 作为对象。但this 确实指的是一个对象。我不明白为什么这是被禁止的
  • @brk 第二部分仅供参考。我的问题是第一次剪断。还是第一个片段在您的环境中运行没有错误?
  • @RadonirinaMaminiaina 从来都不是问题

标签: javascript ecmascript-6 language-lawyer


【解决方案1】:

According to the ECMA spec(我已经用粗体标出了重要的部分):

12.2.6 Object Initializer

NOTE 1 An object initializer is an expression describing the initialization of an Object, written in a form resembling a literal. It is a list of zero or more pairs of property keys and associated values, enclosed in curly brackets. The values need not be literals; they are evaluated each time the object initializer is evaluated.

语法

  • ObjectLiteral[Yield]:
    • { }
    • { PropertyDefinitionList[?Yield] }
    • { PropertyDefinitionList[?Yield] , }
  • PropertyDefinitionList[产量]:
    • PropertyDefinition[?Yield]
    • PropertyDefinitionList[?Yield] , PropertyDefinition[?Yield]
  • 属性定义[产量]:
    • IdentifierReference[?Yield]
    • CoverInitializedName[?Yield]
    • PropertyName[?Yield]:AssignmentExpression[In, ?Yield]
    • 方法定义[?Yield]
  • 属性名称[产量]:
    • LiteralPropertyName
    • ComputedPropertyName[?Yield]
  • 文字属性名称:
    • 标识符名称
    • 字符串文字
    • 数字文字
  • ComputedPropertyName[产量]: -[ 赋值表达式 [In, ?Yield] ]
    • CoverInitializedName[Yield]:
    • IdentifierReference[?Yield] 初始化程序[In, ?Yield]
  • 初始化程序[输入,产量]:
    • = 赋值表达式[?In, ?Yield]

NOTE 2 MethodDefinition is defined in 14.3.

NOTE 3 In certain contexts, ObjectLiteral is used as a cover grammar for a more restricted secondary grammar. The CoverInitializedName production is necessary to fully cover these secondary grammars. However, use of this production results in an early Syntax Error in normal contexts where an actual ObjectLiteral is expected.


12.1 Identifiers

语法

  • IdentifierReference[Yield]:
    • 标识符
    • [~产量] 产量
  • 绑定标识符[产量]:
    • 标识符
    • [~产量] 产量
  • 标签标识符[产量]:
    • 标识符
    • [~产量] 产量
  • 标识符:
    • IdentifierName 但不是 ReservedWord

这意味着在简写中let x = {标识符}不允许保留字作为标识符。而this 是保留字,请看11.6.2 Reserved Words 及以上。 另一方面,我们看到它的扩展方式不同:
let x = {PropertyName:AssignmentExpression} where PropertName 是 ComputedPropertyNameLiteralPropertyName,即不排除保留字的 IdentifierName。因此let x = {this: this}let x = {class: 10} 没有问题。 但是,它并没有解释为什么会这样,也许它会使语法复杂化或使其模棱两可?

【讨论】:

  • 我把最后的解释扩展了,尽量让大家更容易理解。
  • 再次感谢您。现在很清楚firefox和edge的错误消息说的是什么。不过,我有一个(不相关的)问题。 [in] [Yield][?Yield] 是什么意思?
  • 我不知道... O_o 也许是其他人?
  • 这是我在 SO 上看到的最好的答案。干得好 (+1)
【解决方案2】:

Javascript 中的this 是关键字(不是变量),因此它没有名称。

{ x } 的情况下,x 有一个名称“x”,它是值。

但是{ this }this 没有名字。 this 仅代表解释代码时的正确值。

【讨论】:

  • 我认为{this} 将被视为{this:this} 并且该值仅用于第二个this
  • @appleapple 启用 ES2015 支持(左侧 sn-p 中的小叮当),它将完全按照您的预期在 sn-p 中工作。这表明当前浏览器尚不支持 this 的此功能。
  • @Nope 我猜 babel 会把它编译成{this:this},我不确定它是否正确,我想。
  • 根据规范无效(见我的回答)
  • @appleapple 是的,这就是扩展的一般工作方式,但它将第一个 this 视为属性名称(“IdentifierName”),第二个 this 视为变量名称(“标识符") - 它不是。
猜你喜欢
  • 2021-09-30
  • 1970-01-01
  • 2015-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多