微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – ES6中块级功能的精确语义是什么?

我试图通过阅读原始规范来围绕ES6中的新标准化块级功能.我表面上的理解是:

> ES6中允许使用块级函数声明.
他们提升到块的顶部.
>在严格模式下,它们在包含块外不可见.

然而,由于这些语义的一部分被指定为“可选”且仅对网络浏览器(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" |                             |                               |          |

在这种情况下,我还不清楚“严格模式”是什么意思.作为函数声明的运行时执行的一些额外步骤的一部分,这种区别似乎在Annex B3.3中被引入:

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)的严格性.不是要声明的(或不是)的功能的严格性.

“Web扩展”只适用于粗糙(非严格)的代码,只有当函数语句的外观是“一致的” – 就是说,例如,如果它的名称不与正式参数或词汇冲突声明变量.

请注意,没有Web兼容性语义的严格和粗糙的代码之间没有区别.在纯ES6中,块中的函数声明只有一种行为.

所以我们基本上都有

|      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实现如何在具有传统语义的马尔可夫模式函数中的块中执行函数声明?
首先,纯粹的语义仍然适用.也就是说,函数声明被提升到词汇块的顶部.
然而,还有一个var声明被提升到封闭函数的顶部.
并且当函数声明被评估时(在块中,好像像语句一样被满足),函数对象被分配给该函数范围的变量.

这通过代码更好地解释:

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

工作方式相同

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

是的,这有点混乱,有两个不同的绑定(用下标0和1表示),名称相同.所以现在我可以简洁地回答你的问题:

Visible outside of block?

是的,像一个var.但是,第二个绑定只能在块内部显示.

Hoisted?

是的 – 两次

Up to which point?

两个函数(不是初始化为undefined)和块(用函数对象初始化).

“TDZ”?

不是在引用引用时引用的词法声明变量(let / const / class)的时间死区的意义上.但是在执行body之前遇到函数声明,函数范围的变量是未定义的(尤其是在块之前),如果你尝试调用它,你也会得到异常.

原文地址:https://www.jb51.cc/js/153679.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐