javascript - ES6 中 block 级函数的精确语义是什么?

标签 javascript ecmascript-6 language-lawyer

我试图通过阅读原始规范来理解 ES6 中新的标准化 block 级函数。我粗浅的理解是:

  • ES6 中允许使用 block 级函数声明。
  • 他们升到了方 block 的顶部。
  • 在严格模式下,它们在包含 block 之外不可见。

但是,由于这些语义的一部分被指定为“可选”并且仅对 Web 浏览器是强制的 ( Annex B ),这一事实使情况变得更加复杂。所以我想填写下表:

                                             |  Visible outside of block?  |  Hoisted? Up to which point?  |   "TDZ"? |
------------------------------------------------------------------------------------------------------------------------
|   Non-strict mode,   no "web extensions"   |                             |                               |          |
|   Strict mode,       no "web extensions"   |                             |                               |          |
|   Non strict mode,   with "web extensions  |                             |                               |          |
|   Strict mode,       with "web extensions" |                             |                               |          |

Also it is unclear to me what "strict mode" means in this context. This distinction seems to be introduced in Annex B3.3, as part of some additional steps for the runtime execution of a function declaration:

1. If strict is false, then
...

但是,据我所知,strict 指的是函数对象的[[Strict]] 内部槽。这是否意味着:

// Non-strict surrounding code

{
    function foo() {"use strict";}
}

上表中应该被视为“严格模式”吗?然而,这与我最初的直觉相矛盾。

请记住,我最感兴趣的是 ES6 规范本身,无论实际实现的不一致如何。

最佳答案

As far as I can see, strict refers to the [[Strict]] internal slot of the function object.

没有。是的。它确实指的是函数 ( or script ) 的严格性,其中包含函数声明的 block 出现在其中。不考虑要声明(或不声明)的函数的严格性。

“网络扩展”仅适用于草率(非严格)代码,并且仅当函数语句的外观“正常”时 - 也就是说,例如,如果其名称不与正式的冲突参数或词法声明的变量。

请注意,如果没有网络兼容性语义,严格代码和草率代码之间没有区别。在纯 ES6 中, block 中的函数声明只有一种行为。

所以我们基本上有

                 |      web-compat               pure
-----------------+---------------------------------------------
strict mode ES6  |  block hoisting            block hoisting
sloppy mode ES6  |  it's complicated ¹        block hoisting
strict mode ES5  |  undefined behavior ²      SyntaxError
sloppy mode ES5  |  undefined behavior ³      SyntaxError

1:见下文。要求发出警告。
2:通常会抛出SyntaxError
3:ES5.1 §12中的注释谈到“实现之间存在重大且不可调和的差异”(例如 these )。建议发出警告。

现在,具有 Web 兼容性的 ES6 实现对于具有遗留语义的草率模式函数中的 block 中的函数声明有何行为?
首先,纯语义仍然适用。也就是说,函数声明被提升到词法 block 的顶部。
但是,还有一个 var 声明,它被提升到封闭函数的顶部。
当函数声明被求值时(在 block 中,就好像它像语句一样被满足),函数对象被分配给该函数范围的变量。

用代码可以更好地解释这一点:

function enclosing(…) {
    …
    {
         …
         function compat(…) { … }
         …
    }
    …
}

工作原理与

相同
function enclosing(…) {
    var compat₀ = undefined; // function-scoped
    …
    {
         let compat₁ = function compat(…) { … }; // block-scoped
         …
         compat₀ = compat₁;
         …
    }
    …
}

是的,这有点令人困惑,有两个不同的绑定(bind)(用下标 0 和 1 表示)具有相同的名称。现在我可以简洁地回答您的问题:

Visible outside of block?

是的,就像var。但是,还有一个仅在 block 内部可见的绑定(bind)。

Hoisted?

是的 - 两次。

Up to which point?

函数(但使用 undefined 初始化)和 block (使用函数对象初始化)。

"TDZ"?

不是指在引用时抛出异常的词法声明变量 (let/const/class) 的临时死区,不。但在执行主体时遇到函数声明之前,函数作用域的变量是未定义(尤其是在 block 之前),如果你尝试调用它,你也会得到一个异常.

<小时/>

仅供引用:在 ES6 中,上述行为仅针对函数作用域中的 block 指定。 Since ES7这同样适用于 eval 和全局范围内的 block 。

关于javascript - ES6 中 block 级函数的精确语义是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33304808/

相关文章:

javascript - 如何使用 grunt 将 md5 哈希添加到 js 和 css 文件?

javascript - 是否可以根据浏览器宽度动态缩放文本大小?

c++ - 文档/规范中的哪个位置描述了如何在文本模式下将 '\n' 转换为特定于平台的行结尾?

c++ - 模板特化在其实例化点看不到函数

javascript - 为什么会出现错误 var obj= {'A' :'B' ,'C' :obj ['A' ]};?

javascript - jQuery 在加载的模板中缺少目标

javascript - 匿名 JavaScript 函数 f => f 究竟做了什么?

javascript - 为什么 Airbnb 风格指南说不鼓励依赖函数名称推断?

javascript - Angular 的 $http 中返回的 Promise 与普通 Javascript (ES6) 中返回的 Promise 相同吗?

c++ - 显式默认构造函数