首页 文章

一个包罗万象的JavaScript闭包定义

提问于
浏览
4

我已经阅读了关于闭包,MDN参考和其他博客文章的10个SO参考 . 他们似乎都以自己的方式定义闭包 . 例如,从MDN文档:

function makeFunc() {
  var name = "Mozilla";
  function displayName() {
    alert(name);
  }
  return displayName;
}

var myFunc = makeFunc();
myFunc();

这里是关闭的解释:

通常,函数中的局部变量仅在该函数执行期间存在 . 一旦makeFunc()完成执行,就可以预期名称变量将不再可访问 . 由于代码仍然按预期工作,显然不是这种情况 . 这个难题的解决方案是myFunc已成为一个闭包 . 闭包是一种特殊的对象,它结合了两个东西:一个函数,以及创建该函数的环境 . 环境由创建闭包时在范围内的任何局部变量组成 . 在这种情况下,myFunc是一个闭包,它包含displayName函数和创建闭包时存在的“Mozilla”字符串 .

这下面的StackOverflow帖子将闭包作为一堆可见范围来回答 . What types of scope exist in Javascript?

我困惑的地方:关闭一个物体?或者它只是一个"anomalous scoping situation",其中内部嵌套函数可以访问在其自身之外定义但在容器父函数本地的变量,即使父函数已经执行了?闭包是一个引用这个嵌套函数(范围)情况的对象,如 myFunc ,还是内部函数本身?

3 回答

  • 0

    简而言之,

    另一个函数内部的函数,可以访问外部函数中声明的变量 . 如果函数在全局上下文中,它显然可以访问全局变量 .

    更多背景:

    var v1; // I'm accessible anywhere    
    function a() {
        var v2;
        function b() { // I can access v2 and v1
            var v3;
            function c() {  // I can access v1, v2, v3
                var v4;
            }
            return c;
        }
        return b();
    }
    var f = a();
    

    在上面, abc 都是闭包,它们可以访问它们各自的父作用域,并且递归到 window 或全局上下文 .


    通常,每个函数都是一个闭包 . 但是,当我们实现某些东西时,我们只会想到它们,这实际上取决于封闭,例如工厂功能 .

  • 2

    您可以将JS函数视为此结构:

    class Function : Object {
      bytes      bytecode;
      varframe   varsAndArgs;
    }
    
    class varframe{
      array<value>  values;
      ptr<varframe> parent;
    }
    

    所以JS中的每个函数实例在技术上都是一个闭包 . 在父指针为空的顶层函数中 .

    所以当你定义时

    function makeFunc() {
      var name = "Mozilla";
      function displayName() {
        alert(name);
      }
      return displayName;
    }
    

    displayName(const / variable)将包含类Function的实例,该实例将包含对此结构自己的varframe的引用:

    varframe(displayName) 
      values[0] // empty array, no variables in it
      parent -> varframe(makeFunc) 
                  values[1] // one variable "name" at index 0;
                  parent = null
    

    因此,闭包是一种结构,它保存对代码链的引用和对varframe链的引用(a.k.a.callframes) .

  • 1

    在过去,许多课程材料和参考文献强调JavaScript的OO方面有时忽略了功能方法 . 我认为随着框架的发展和JS库的广泛收集,这种情况开始发生变化 . Secrets of the JavaScript Ninja假设母带处理函数是有效使用JavaScript的基本部分 . 在 Ninja 中,闭包的定义更为通用:

    “...闭包允许函数访问声明函数本身时范围内的所有变量以及其他函数 . ” - “第5章:关闭封闭”

    讨论闭包,Effective JavaScript这样(或多或少)这样:

    • 函数可以引用在其范围之外定义的变量;

    • 函数可以在第二个函数返回后引用另一个函数定义的变量(因为在JavaScript函数中是对象);

    • 一个函数可以包含"closed over"的内部函数,它可以修改封闭函数的属性 .

    有效的JavaScript第2章的源代码 . 项目11“通过闭包获得舒适”在gibhub上:

    关于一个封闭函数的巧妙之处在于,如果你不打算明确地调用它,它就不需要名字:它可以是匿名的,只是作为外部函数的一部分进行评估 .

相关问题