ES6中块级功能的精确语义是什么? [英] What are the precise semantics of block-level functions in ES6?

查看:134
本文介绍了ES6中块级功能的精确语义是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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




  • ES6中允许使用块级功能声明。

  • 他们提升

  • 在严格模式下,它们在包含块外不可见。



然而,由于这些语义的一部分被指定为可选且仅对Web浏览器是必需的(附件B )。所以我想要下列表格填写:

 
|可见外面的块? |悬挂?到哪一点? | TDZ? |
---------------------------------------------- -------------------------------------------------- ------------------------
|非严格模式,没有Web扩展| | | |
|严格模式,没有Web扩展| | | |
|不严格的模式,带有Web扩展名| | | |
|严格模式,带有web扩展名| | | |

另外还不清楚这种情况下的严格模式是什么意思,这个区别似乎是在附件B3.3 ,作为运行时执行函数声明的一些额外步骤的一部分:

  1。如果strict为false,则
...

然而,据我所见, strict 是指 [[Strict]] 函数对象的内部插槽,这是否意味着:

  //非严格的周边代码

{
function foo(){use strict;}
}


但是,这与我的初步直觉相矛盾。



请记住,我对ES6规范本身感兴趣,不管实际的实现不一致。

解决方案


据我所见, strict [[Strict]] 功能对象的内部插槽。


没有。是的。它确实提到功能的严格性(或脚本其中将发生包含函数声明的块。不是要声明的(或不是)的功能的严格性。



Web扩展只适用于马虎(非严格)代码,并且只有当函数语句的外观是正常的 - 例如,如果它的名称不与正式参数或词汇声明的变量相冲突。



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



所以我们基本上有

  | web-compat纯
----------------- + ------------------------ ---------------------
严格模式ES6 |块吊装块
马虎模式ES6 |这是复杂的¹块提升
严格模式ES5 |未定义的行为²SyntaxError
sloppy模式ES5 |未定义的行为³SyntaxError

1:见下文。要求提供警告。

2:通常,会抛出一个 SyntaxError

3:ES5.1§12谈论实现中的重要和不可调和的变体(例如这些)。建议使用警告。



现在,具有Web兼容性的ES6实现如何在具有传统语义的马虎模式函数中的块中的函数声明?

首先,纯语义仍然适用。也就是说,函数声明被提升到词汇块的顶部。

但是,还有一个 var 声明被挂起到封闭函数的顶部。

当函数声明被计算时(在块中,就像它像语句一样被满足),函数对象是 / strong>到该函数范围的变量。



这可以通过代码更好地解释:

 函数包围(...){
...
{
...
函数compat(...){...}
...
}
...
}

的工作方式与


相同

 函数封闭(...){
var compato = undefined; // function-scoped
...
{
let compat 1 = function compat(...){...}; // block-scoped
...
compat0 = compat 1;
...
}
...
}

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


在块之外可见


是的,像一个 var 。但是,有一个第二个绑定只能在块中显示。


Hoisted?


是 - 两次。


到底是什么?


两个函数(但是初始化为 undefined )和块(使用函数对象初始化) / p>


TDZ?


一个词汇声明变量的时间死区的感觉( let / const / class )引用引用,否。但是在执行body之前遇到函数声明,函数范围的变量是 undefined (尤其是在块之前),你也会得到一个异常如果你尝试调用它。


I'm trying to wrap my head around the new standardized block-level functions in ES6 by reading the raw spec. My superficial understanding was:

  • Block-level functions declarations are allowed in ES6.
  • They hoist to the top of the block.
  • In strict mode, they aren't visible outside the containing block.

However, this is further complicated by the fact that part of these semantics are specified to be "optional" and only mandatory for web browsers (Annex B). So I would like have the following table filled:

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

However, as far as I can see, strict refers to the [[Strict]] internal slot of the function object. Does this mean that:

// Non-strict surrounding code

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

should be considered "strict mode" in the table above? However, that's contradicts my initial intuition.

Please, bear in mind that I'm mostly interested in the ES6 spec itself, regardless of actual implementation inconsistencies.

解决方案

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

No. And yes. It does refer to the strictness of the function (or script) in which the block that contains the function declaration occurs. Not to the strictness of the function that is (or is not) to be declared.

The "web extensions" do only apply to sloppy (non-strict) code, and only if the appearance of the function statement is "sane" - that is, for example, if its name doesn't collide with a formal parameter or lexically declared variable.

Notice that there is no difference between strict and sloppy code without the web-compatibility semantics. In pure ES6, there is only one behaviour for function declarations in blocks.

So we basically have

                 |      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: See below. Warnings are asked for.
2: Typically, a SyntaxError is thrown
3: The note in ES5.1 §12 talks of "significant and irreconcilable variations among the implementations" (such as these). Warnings are recommended.

So now how does an ES6 implementation with web compatibility behave for a function declaration in a block in a sloppy-mode function with legacy semantics?
First of all, the pure semantics still apply. That is, the function declaration is hoisted to the top of the lexical block.
However, there is also a var declaration that is hoisted to the top of the enclosing function.
And when the function declaration is evaluated (in the block, as if it was met like a statement), the function object is assigned to that function-scoped variable.

This is better explained by code:

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

works the same as

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

Yes, that's a bit confusing, having two different bindings (denoted with the subscripts 0 and 1) with the same name. So now I can succinctly answer your questions:

Visible outside of block?

Yes, like a var. However, there's a second binding that is visible only inside the block.

Hoisted?

Yes - twice.

Up to which point?

Both to the function (however initialised with undefined) and the block (initialised with the function object).

"TDZ"?

Not in the sense of the temporal dead zone of a lexically declared variable (let/const/class) that throws on referencing, no. But before the function declaration is encountered in the execution of the body, the function-scoped variable is undefined (especially before the block), and you'll get an exception as well if you try to call it.

这篇关于ES6中块级功能的精确语义是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆