2017-01-23 102 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'。 –