2016-12-14 72 views
4

我試圖讓我的頭繞着範圍界定。根據我的理解,ES5不具備阻塞範圍的能力,因此,內部f()應該位於身體測試的範圍內。在JavaScript和內部函數中使用塊範圍

這些是從運行功能

  • 測試(真)的結果; // [ 「本地」, 「本地」]
  • 測試(假)// f不是定義

不過,我不明白爲什麼測試(假)給出了一個錯誤?我期待 - [本地]。

function f() { return "global"; } 

    function test(x) { 
     var result = []; 
     if (x) { 
      function f() { return "local"; } // block-local 

      result.push(f()); 
     } 
     result.push(f()); 
     return result; 
    } 
+0

[非常相似的問題。](http://stackoverflow.com/q/10069204/417562) – lonesomeday

+1

哈!如果您在Chrome 54中使用「嚴格」模式,則結果爲[「本地」,「全局」],[「全局」]。所以它似乎通過在'if'中創建範圍來修復事情。我認爲這不應該被允許,因此不一致的結果。否則,這是瀏覽器中的一個錯誤,因爲根據我的理解,函數應該在整個函數中可用,並且不受'if'影響。 –

回答

3

這是你的代碼實際上看起來,當它被編譯,如:

function f() { return "global"; } 

    function test(x) { 
     var result = []; 
     var f; 
     if (x) { 
      f = function() { return "local"; } // block-local 

      result.push(f()); 
     } 
     result.push(f()); 
     return result; 
    } 

f變量(變量保存函數指針)在函數的頂部聲明,但它是在條件內定義的。

JavaScript還具有一個稱爲strict mode的功能。這是在語言的最初開發之後實施的,以強制實施一些最佳實踐和一些規則,以防止開發人員根據其他語言使用類似的語法對他們的語言如何工作做出不正確的假設。在這種情況下,嚴格模式實際上改變了新的f函數的範圍。

下面的代碼:

function f() { return "global"; } 

    function test(x) { 
    "use strict" // STRICT MODE TAG INSERTED HERE 
     var result = []; 
     if (x) { 
      function f() { return "local"; } // block-local 

      result.push(f()); 
     } 
     result.push(f()); 
     return result; 
    } 

test(true); 
test(false); 

產生以下結果導致:

["local","global"] //test(true); 

["global"] //test(false); 

它將覆蓋默認作用域規則,並確保的f的新的聲明僅適用於內有條件的地方它被定義了。

+1

很高興提到嚴格模式有多不同。 – georg

+0

好點,我會努力添加它。 – kemiller2002

0

這是因爲當你的條件爲真時,'f'是一個函數聲明,所以它檢查內部f函數。

當x是假的,因爲「F」是不可見的,它拋出一個錯誤,它無法看到全局的「F」功能,因爲F在本地

已經覆蓋要覆蓋您可以顯式調用if條件內的window.f()或使f()的一個IIFE

檢查這些片段

function f() { 
 
    return "global"; 
 
} 
 

 
function test(x) { 
 

 
    var result = []; 
 
    if (x) { 
 

 
    // block-local 
 
    result.push((function f() { 
 
     return "local"; 
 
    })()); 
 
    } 
 
    result.push(f()); 
 
    return result; 
 
} 
 
var res = test(true); 
 
console.log(res); 
 
var res1 = test(false); 
 
console.log(res1);

希望它可以幫助

+0

非常感謝,非常明確,比教科書更好。這現在是有道理的。 – stckpete