Javascript中的范围链和在全局范围内调用嵌套函数

Posted

技术标签:

【中文标题】Javascript中的范围链和在全局范围内调用嵌套函数【英文标题】:Scope chain in Javascript and calling nested function within the global scope 【发布时间】:2015-11-25 19:55:08 【问题描述】:

这是我想要启发的示例(实际上不起作用的东西)。

 var myVar = 2;

    function a()
     var myVar = 2;
        function b()
            console.log(myVar);
        
    ;
   a();
   b();

这会在控制台输出:Uncaught ReferenceError: b is not defined。

如您所见,我有一个名为 a 的函数和一个名为 b 的嵌套函数。

起初我以为我可以在 a 之外调用 b 并让它正常工作。 我认为这会起作用,因为一开始我调用了 a 函数。

通过这样做,我想到了 a 函数 将被放入执行堆栈中,并且在其创建阶段,将设置内部定义的 b 函数在记忆中。

因为这是在内存中,所以我想我可以在函数之外执行它。这显然行不通。

所以我的结论是 b 函数 确实在 a 函数 的创建阶段被设置到内存中,但是一旦 a 函数 具有执行完毕,一旦从执行栈中弹出,b函数同时从内存中弹出。

因此在全局范围内调用它(我的意思是 b 函数)是不可能的。

我说对了吗?

【问题讨论】:

javascriptlexical scope 并且也适用于函数。 【参考方案1】:

您通过谈论执行堆栈、创建阶段等使事情变得不必要地复杂化。

解释很简单:您不能调用b,因为规范说b 超出了您尝试调用它的站点的范围。就是这样,故事结束。

如果转换为 php,您的示例实际上会起作用,这让我认为这也许就是您的灵感来源。但是 JS 和 PHP 是不同的语言,PHP 对待嵌套函数的(IMO 荒谬的)方式并没有转移。

【讨论】:

是的,你是对的,我试图在反思中走得太深......我知道我不能在 Javascript 中做到这一点,但我试图完全理解为什么。涉及的所有机制。但实际上它更简单。解释是名为“b”的函数位于名为“a”的函数内。然后当我们尝试从全局范围调用它时它会失败,因为全局执行环境会寻找函数 b,但在全局执行上下文的创建阶段从未将它添加到其变量环境中......总结一下,它们与您告诉我的范围不同。谢谢【参考方案2】:

如果你想在a之外调用b,你需要在a之外创建对它的引用:

var myVar = 2;

function a()
  var myVar = 2;
  function b()
      console.log(myVar);
  
  return b;
;

var b = a();
b();

但这不会导致b 打印全局myVar。它仍然可以访问a 的闭包范围内的myVar

【讨论】:

以上是关于Javascript中的范围链和在全局范围内调用嵌套函数的主要内容,如果未能解决你的问题,请参考以下文章

如何从全局范围调用 jquery 函数内的方法?

在 JavaScript 中存储的全局范围内创建的常量在哪里?

JavaScript之作用域,作用域链和预解析

需求和内存:用于全局或功能范围

检查变量是不是设置在全局范围内?

函数②