2016-12-26 86 views
1

以下代碼將輸出「1」。然而,關鍵字「let」不應該使x成爲一個全局變量,從而使它對das()不可見?我們應該將變量的範圍限制在聲明的塊中,但在這裏,我看到一個內部函數可以訪問「let」變量,儘管x在其範圍之外被聲明。這怎麼可能?讓可變範圍

function letTest() { 
 
\t function das() { 
 
\t \t console.log(x); 
 
// How does this function have access to a let variable declared outside its scope? 
 
\t } 
 

 
\t let x = 1; 
 
\t das(); 
 
} 
 
letTest();

+0

我認爲這是因爲'das'是在'x'定義的塊中,就在2個塊的內部,但其中一個也包圍了'let',所以它很好 – Max

+2

'x'沒有爲* global *以便它在嵌套函數中可見;它只需要在本地範圍或某個外部範圍內。 「let」聲明不會限制僅限於本地範圍的可見性;它是本地範圍和任何嵌套範圍。 – Pointy

+3

換句話說,嵌套函數**內部的代碼是**包含'let'的塊的一部分。 – Pointy

回答

3

這裏是思考的一種方式let是如何工作的:

  1. let開始。
  2. 在相同的嵌套層次上,通過源代碼回溯/提升,找到第一個{
  3. 現在從let找到相應的}

這給出了變量可見的範圍。如果函數定義出現在該範圍內,則罰款;該變量對該函數中的代碼可見。現在

,什麼是有點不可思議的是,在你的榜樣變量看起來它是在它的聲明之前範圍使用。這就是參考文獻出現在聲明之前的事實變得更加有趣的事實。

通常情況下,如果範圍中的代碼指的是實際發生let之前的let聲明的變量,那是錯誤的。然而,這是一個運行時的事情,而不是語法的事情。在你的情況下,在運行時let將在嵌套函數被調用時發生。

+0

所以「讓」限制外部範圍,而不是內部範圍? –

+1

@GTSJoe我剛纔評論了另一個答案。沒有「內部範圍」這樣的東西。 – Pointy

+1

@GTSJoe換言之,嵌套函數體的'{}'與作用域中出現的'for'循環的'{}'沒有區別。 – Pointy

1

let限制變量的當前塊範圍(在這種情況下是一樣的letTest功能)。

das函數在該範圍內聲明,因此它有權訪問該範圍內的任何內容(包括x)。

0

問題是你沒有改變x的值,在你的情況下,你只是將它記錄到控制檯,它們都嵌套在一個不限制內部函數的範圍內,所以你的結果是預期的。現在

,如果你做了這樣的事情

function letTest() { 
    function das() { 
     console.log(x); 
// How does this function have access to a let variable declared outside its scope? 
    } 
    let x = 1; 
    function change(){ 
     x = x + 1; 
    } 

    change(); 
} 
letTest(); 

現在你正在試圖改變x的值,編譯器會抱怨。

0

如此處所述:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let它提供了在塊範圍內的訪問。由於您的das()執行和x聲明處於相同的塊範圍,因此它將具有訪問權限。

一個很好的例子是在下面的開關的情況下,在殼體1使用var x = 'x'將導致其附着到功能範圍和訪問在執行console.log(),但嘗試參照杆變量用於記錄當它拋出一個參考例外。但仍然適用於默認情況。

const example = (foo) => { 
    switch(foo) { 
     case 0: 
      break; 
     case 1: 
      let bar = 'bar'; 
      var x = 'x'; 
      break; 
     default: 
      console.log(bar); 
      break; 
    } 

    console.log(x); 
    console.log(bar); 
} 

example(1); 
0

的功能在同一個塊作爲x聲明的,所以該函數內的代碼訪問x

如果你不希望出現這種情況,你可以隨時添加新的模塊:

function letTest() { 
 
    function das() { 
 
    console.log(x); // ReferenceError 
 
    } 
 
    { // New block 
 
    let x = 1; 
 
    das(); 
 
    } 
 
} 
 
letTest();

0

@GTS喬,

let x是本地letTest()背景下,因此das()只是訪問其變量x。沒有什麼奇怪的是在那裏。所以,'不' - 它不會成爲全球性的。

無論上下文中的變量調用有多深已經被嵌套,總有一個查找JS原則,將遵循一個失敗看看周圍將繼續在整個全局範圍內查找這個變量名稱,只有這樣 - 當沒有發現任何東西時 - 它會導致引用錯誤。

這 - 只是因爲沒有看看下面 JS原則 - 即所謂的封是可能的。