pidtfork 发表于 2020-10-28 17:45:22

JavaScript闭包

本帖最后由 pidtfork 于 2020-10-28 17:55 编辑

JavaScript闭包一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是 闭包(closure)。
也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

词法作用域

function init() {
    var name = "ubains";      // name 是一个被 init 创建的局部变量
    function displayName() {    // displayName() 是内部函数,一个闭包
      console.log(name);      // 使用了父函数中声明的变量
    }
    displayName();
}
init();


init() 创建了一个局部变量 name 和一个名为 displayName() 的函数。displayName() 是定义在 init() 里的内部函数,并且仅在init() 函数体内可用。
请注意,displayName() 没有自己的局部变量。然而,因为它可以访问到外部函数的变量,所以 displayName() 可以使用父函数 init() 中声明的变量 name 。
运行该代码后发现, displayName() 函数内的打印了变量 name 的值(该变量在其父函数中声明)。这个词法作用域的例子描述了分析器如何在函数嵌套的情况下解析变量名。
词法(lexical)一词指的是,词法作用域根据源代码中声明变量的位置来确定该变量在何处可用。嵌套函数可访问声明于它们外部作用域的变量。


闭包

function foo() {
    var a = 10;
    return function () {
      a*= 2;
      return a;
    };
}
var f = foo();
f(); //return 20.
f(); //return 40.


函数在外部调用,依然可以访问变量a。这都是因为javascript中的作用域是词法性的。函数式运行在定义它们的作用域中(例子中的foo内部的作用域),而不是运行此函数的作用域中。
只要f被定义在foo中,它就可以访问foo中定义的所有的变量,即便是foo的执行已经结束。因为它的作用域会被保存下来,但也只有返回的那个函数才可以访问这个保存下来的作用域。
返回一个内嵌匿名函数是创建闭包最常用的手段。


闭包的作用

闭包可以用在许多地方。一个是第一个例子可以读取函数内部的变量不允许外部访问,也就是使用闭包来模拟私有方法。另一个就是第二个例子让这些变量的值始终保持在内存中。








页: [1]
查看完整版本: JavaScript闭包