2017-01-23 101 views
2

我读this book on ES6,并有以下几点:为什么功能描述块范围的

Function declarations…

  • are block-scoped, like let.
  • create properties in the global object (while in global scope), like var.
  • are hoisted: independently of where a function declaration is mentioned in its scope, it is always created at the beginning of the scope.

据我所知,功能一直是功能范围的。我想可能在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变化?

+0

我认为这本书使用(现有)函数声明作为例子来解释'let'如何适合图片。 – Lucero

+1

那是因为你在松散模式下执行它。在严格模式下,它应该如预期的那样。 – estus

回答

5

AFAIK, functions have always been function scoped. I thought something might have changed in ES6

它做到了:在ES2015之前,规范并没有涵盖在块内声明的函数。支持它们是允许的扩展,但不是规范的一部分。

因此,该规范必须跳过这个箍环,特别是在浏览器上的松散模式下。

严格模式,你会发现一个兼容的引擎,函数声明确实是块作用域:

"use strict"; 
 

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

在一个标准的JavaScript引擎(如V8在任何最新版本的Chrome,或任何最新版本的Firefox中的SpiderMonkey),您将在上面获得ReferenceError

+0

@TJCrowder在Firefox上,我得到了这个SyntaxError:在严格模式代码中,函数可能只在顶级或在另一个函数内声明 – Eineki

+0

@Eineki:这必须是一个相当旧的Firefox版本(“旧”是一个相对的术语在ES2015-support-land中:-))。我在Firefox v50.1.0中得到了预期的'ReferenceError'。 –