当前位置: 首页 > 面试题库 >

JavaScript ES6中块级功能的确切语义是什么?

慕容晔
2023-03-14
问题内容

我正在尝试通过阅读原始规范来围绕ES6中新的标准化块级功能进行研究。我的肤浅理解是:

  • ES6中允许块级函数声明。
  • 他们吊在街区的顶部。
  • 在严格模式下,它们在包含块之外不可见。

但是,由于这些语义的一部分被指定为“可选”且仅对于Web浏览器是强制性的(附件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" |                             |                               |          |

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

1. If strict is false, then
...

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

// Non-strict surrounding code

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

在上表中应被视为“严格模式”?但是,这与我最初的直觉相矛盾。

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


问题答案:

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

不,是的。它确实是指函数或脚本的严格性,其中包含函数声明的块出现在其中。不严格于要(或不要)声明的功能。

“ 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抛出a。3:ES5.1§12中的注释谈到“实现之间的重大和不可调和的变化”(例如这些)。建议警告。

那么,具有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)的时间盲区上,不是。但是,在执行主体时遇到函数声明之前,函数作用域变量是undefined(尤其是在块之前),并且如果尝试调用它,也会获得异常。

仅供参考:在ES6中,仅针对函数作用域中的块指定了上述行为。从ES7开始,这同样适用于eval全局范围内的块。



 类似资料:
  • 我偶然发现了表达式通过android-在xml中应用selectableItembackground并支持v7。 我想看看该表达式的确切功能,因为我不明白开头的问号象征着什么以及它是如何准确地完成任务的。 它说它是支持库v7的一部分,但我试着查找它,却找不到有用的信息 到底是什么, 定义它的位置和 它到底是做什么的。

  • (...)当您在非托管环境中使用JmsTemplate时,您可以通过使用属性SessionTransact和SessionAccountingEmode来指定这些值(事务和确认模式)。 当您将PlatformTransactionManager与JmsTemplate一起使用时,模板总是被赋予一个事务性JMS会话。(..) (顺便说一句,这是真的--会话是事务性的) 我调试了它不正确的原因,发现:

  • 这两天我一直在和Git Bash合作。我现在知道了诸如、、、和等基本操作。但我还是不知道Git Bash本身到底是什么! 我已经搜索了很多关于Git Bash的内容,但是我看到的所有站点都集中在它的命令的功能上。我仍然没有为我的问题找到一个好的答案。现在,我想,我在正确的地方得到这个答案!

  • 假设我们使用自动提交模式,即:。 默认情况下(没有BEGIN),PostgreSQL以“自动提交”模式执行事务,即每个语句都在自己的事务中执行,并在语句末尾隐式执行提交(如果执行成功,否则回滚完成)。 然后,使用读取提交的隔离级别(在 postgresql 中也是缺省值),该语句是实际的隔离单元。但在这里,这句话只意味着外在的陈述?同一外部语句中嵌入的语句呢? CTE(带查询) 我测试了一些情况,

  • 问题内容: 我是JAVA的新手,因此遇到了这个词。“在方法内部创建的类,在Java中称为本地内部类。如果要调用本地内部类的方法,则必须在方法内部 实例化 该类”。粗体字。任何人都可以帮我解决这个问题。我知道这很尴尬,我应该做更多的研究,但我只是不明白。谢谢。 问题答案: 首先 声明的意思是 : 实例化的 简单含义 是从class创建一个对象 。 什么是物体? 类的实例。从一个类中,我们可以创建许多

  • 问题内容: 我想在同一类对象的各种实例之间共享一个对象。 从概念上讲,在我的程序运行时,类A的所有对象都访问类B的相同对象。 我已经看到这是系统范围的,不鼓励使用它。这是否意味着如果我在实例化类A的对象的同一JVM上运行另一个程序,则这些对象可能会访问与先前程序中访问的对象相同的B对象? 使用静态字段的一般缺陷是什么? 是否有其他选择(不需要大量的实施工作)? 问题答案: 静态不是完全意味着“由所