在讲闭包之前,我们先了解一下什么是自由变量。
示例代码: let a = 1; 上述代码中,对于函数 foo 来说,a 既不是函数参数也不是函数的局部变量的变量,因此 a 属于自由变量。 什么是闭包在ECMAScript中,闭包(Closure)是指能够访问自由变量的函数。 按照以上的概念,我们可以说所有函数都是闭包,因为它们都是在创建的时候就保存了上层上下文的作用域链,观察如下代码: let a = 1; ECMAScript 使用的是词法作用域(Lexical scoping,又称静态作用域),即在函数创建时,就保存上层上下文的作用域链,上述代码中,foo 函数创建时,其所使用的变量 a 是已经在上下文中静态保存好的,因此在执行 foo() 时 a 的值为 1。 而任何函数,在其创建时保存的上层上下文的作用域中都有全局的自由变量 global(在浏览器中,global 为 window),因此说所有函数都是闭包。 实践中的闭包上面说的是理论上的闭包,但在实践中,闭包不仅仅只是能够访问自由变量的函数,闭包是指引用了自由变量的,并且被引用的自由变量将和这个函数一同存在的函数,在创建该函数的上下文已经销毁时,该函数仍然存在。 示例代码: function foo(){ 上述代码中,foo 函数执行后返回了一个匿名函数,该函数引用了自由变量 a,而在 foo() 执行完毕后,创建该函数的环境已经销毁,但该函数并没有被销毁,因此 foo() 的返回值就是一个闭包。 闭包会使引用的自由变量不能被清除,这就使得闭包比其他函数占用内存更多,但这也是闭包的强大之处,以下是一个使用闭包的例子: let foo = function() { 再来看一个面试中经常遇到的题目: let data = []; 这三个函数创建时均使用的是已经在上下文中静态保存好的变量 i,而在 for 循环结束时,变量i 的值为3,当 我们的目标是输出0、1、2,上面的例子显然无法实现这个需求,利用闭包可以很轻松地解决这个问题: let data = []; |
|
来自: 昵称10087950 > 《JAVA》