为啥函数被描述为块范围

Posted

技术标签:

【中文标题】为啥函数被描述为块范围【英文标题】:Why functions are described as block scoped为什么函数被描述为块范围 【发布时间】:2017-06-07 19:50:02 【问题描述】:

我正在阅读this book on ES6 并且有以下内容:

函数声明…

是块范围的,例如 let。 在全局对象中创建属性 (在全局范围内),如 var. 被吊起:独立于何处 函数声明在其范围内被提及,它总是被创建 在范围的开头。

AFAIK,函数一直是函数作用域的。我认为 ES6 中可能发生了一些变化,但没有:

function a() 
    if (true) 
        // defined inside the block and is hoisted to the top of that block
        z();
        function z()  console.log ('z')
    

    z();


// but is also hoisted to the function scope
a(); // works OK

实际上,它们似乎是块作用域:

function a() 
    if (false) 
        // defined inside the block and is hoisted to the top of that block
        z();
        function z()  console.log ('z')
    

    z(); // error

那么它在 ES6 中是否发生了变化?

【问题讨论】:

我认为这本书以(现有的)函数声明为例来解释let如何融入图片。 那是因为你在松散模式下执行它。在严格模式下,它应该符合预期。 【参考方案1】:

AFAIK,函数一直是函数作用域的。我认为 ES6 中可能发生了一些变化

确实如此:在 ES2015 之前,规范根本没有涵盖在块中声明的函数。支持它们是允许的扩展,但不是规范的一部分。

因此,规范不得不跳槽,尤其是在浏览器的松散模式下。

strict 模式下,您会在兼容的引擎上发现函数声明确实是块范围的:

"use strict";

function test() 
  if (true) 
    function foo() 
      console.log("foo called");
    
  
  try 
    foo(); // ReferenceError
   catch (e) 
    console.log("Error: " + String(e));
  

test();

在兼容的 javascript 引擎上(例如任何最新版本的 Chrome 中的 V8,或任何最新版本的 Firefox 中的 SpiderMonkey),您将在上面获得ReferenceError

【讨论】:

@TJCrowder 在 firefox 上我得到这个 SyntaxError:在严格模式代码中,函数只能在顶层或立即在另一个函数中声明 @Eineki:那一定是一个相当老的 Firefox 版本(“老”在 ES2015-support-land 中是一个相当相对的术语 :-))。我在 Firefox v50.1.0 中得到了预期的 ReferenceError

以上是关于为啥函数被描述为块范围的主要内容,如果未能解决你的问题,请参考以下文章

为啥“<<-”会与 Shiny 中的函数范围混淆

为啥我的 HelloWorld 函数没有在这个范围内声明?

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

当函数返回时,指向超出范围的对象的 C++ 指针 - 为啥会这样?

为啥 dolphindb 脚本中的函数无法访问外部范围内的变量

为啥 GLfloat 需要全局范围?