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

时间:2015-01-29 16:54:04

标签: javascript closures scope scopes lexical

我已经阅读了关于闭包,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?

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

3 个答案:

答案 0 :(得分:2)

简明扼要地说,

  

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

更多背景信息:

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或全局上下文


通常,每个函数都是一个闭包。但是,当我们实现某些东西时,我们只会想到它们,实际上依赖于闭包,例如工厂函数。

答案 1 :(得分:1)

您可以将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    

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

答案 2 :(得分:0)

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

  

&#34; ...闭包允许函数访问声明函数本身时范围内的所有变量以及其他函数。&#34;

                                         -- "Chapter 5: Closing in on closures"

讨论闭包,Effective JavaScript以这种方式(或多或少)表达它:

  • 函数可以引用在其范围之外定义的变量;
  • 函数可以在第二个函数返回后引用另一个函数定义的变量(因为在JavaScript函数中是对象);
  • 一个函数可以包含“关闭”的内部函数。并且可以修改封闭函数的属性。

有效JavaScript第2章的源代码。第11项&#34;通过闭包获得舒适&#34;在gibhub上:

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