2016-12-14 66 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