作为对象键的函数与块中的标记函数之间的Javascript语法冲突

Posted

技术标签:

【中文标题】作为对象键的函数与块中的标记函数之间的Javascript语法冲突【英文标题】:Javascript Conflicting Syntax Between Function As Object Key And Labeled Function in Block 【发布时间】:2017-06-15 21:01:04 【问题描述】:

假设您有一个同时支持labeled function declarations 和block statements 的浏览器,浏览器确定以下是否为具有名为L 的属性的对象的标准方式/方法是函数F,或包含函数F 的块标记为L


    L: function F()

例如

为了公开我的意思,这里是上述代码的两个不同副本,经过修改以将其公开为数组和函数:

document.body.textContent = typeof( () => 
    L: function F()
 )

在上面的代码中,浏览器识别箭头函数符号并确定它是一个块语句。然而,

document.body.textContent = typeof 
    L: function F()

上面的代码让浏览器认为它是一个写成对象字面量的对象,索引L是函数F

【问题讨论】:

【参考方案1】:

您可以将问题简化为:浏览器如何知道 是否启动以及何时启动对象字面量

答案是,如果 出现在语句位置,JS 引擎会将其视为块的开始,如果它位于表达式位置,则将其视为对象字面量的开始。

这就是为什么当 出现在语句位置但您想要一个对象时,您必须在它们周围添加括号 (())。

标签函数声明的引入根本没有改变情况,因为情况已经很模糊:


  foo: 42


再看spec,其实是指出了这个歧义:

ExpressionStatement 不能以 U+007B(左大括号)开头,因为这可能会使其与 Block 混淆。

(语法也反映了这一点)

【讨论】:

能否请您在标准中说明这一点的地方添加引文。 (我完全同意这一点,但我仍然对血腥细节感到好奇) 规范中没有这样写,但它遵循语法规则:ecma-international.org/ecma-262/7.0/…。 解析器只是尝试匹配规则。在顶部你有一个 Script,它有一个 ScriptBody,它有一个 Statement 列表等 箭头符号是一个例外。例如,使用箭头符号,如果() => 3 创建一个返回 3 的函数,那么逻辑上() => L: function F() 应该创建一个返回一个对象的函数。但这不是这种方式,这意味着它必须更复杂。 没有那么复杂,但是是的,箭头函数还有额外的规则:ecma-international.org/ecma-262/7.0/…。正文可以是开头的表达式,也可以是,后跟语句列表,然后是【参考方案2】:

嗯...我认为:

if(1) // the brackets here belong to the if statement == block
    L: function F()

在这里:

console.log( // the brackets represent JSON (javascript object notation) 
    L: function F()
)

这确实是一个带有“L”索引的对象

【讨论】:

这不能回答问题。你刚刚重述了这些例子。您似乎没有列出任何有关浏览器如何区分它们的信息(在代码的第一个 sn-p 中)。 我同意上面的答案更详细

以上是关于作为对象键的函数与块中的标记函数之间的Javascript语法冲突的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL 错误“字段必须是以字段名称作为键的对象或返回此类对象的函数。”

面试中的JavaScript之函数对象数组.md

错误:对象作为 React 子对象无效(找到:带键的对象..........)

为啥条件块中的函数声明在 Chrome 而不是 Firefox 中提升到函数范围?

查找算法--Block search--分块查找

如何从 Javascript 中的对象列表中获取键的值?