先导知识:

  • JavaScript中作用域有两大类:全局作用域局部作用域
  • JavaScript中变量有:全局变量局部变量
  • JavaScript中没有命名空间的概念
  • JavaScript中函数内可以嵌套定义函数
  • 在函数局部作用域中可以访问全局变量,反之不行。

Question:我们需要在全局作用域中访问局部作用域中的局部变量,为了解决这个问题,有了闭包的概念。

一、定义

《javascript高级程序设计》:闭包是指有权限访问一个函数作用域中局部变量的函数。

二、展示

假设我们需要一个计数器变量count,用来计数。这时我们可以这样去写。

/**
 * 直接定义全局变量用来计数
 */
var count = 0;

但是这样一来任何,任何地方都可以访问这个变量,而且会有被重新赋值的危险。

所以我们可以这样去写:

/**
 * 将计数变量放到函数内部
 */
function count(){
    var count = 0;
    return count += 1;
}

count();    // 1
count();    // 1

但是这样就会一直输出1,以为每次调用都会重新定义一个count并初始化这个变量。

那再改造一下:

/**
 * 改造版的计数器实现
 */
function counter(){
    let count = 0;
    function plus(){
        count += 1;
    }
    plus();
    return count;
}
console.log(counter());     // 1
console.log(counter());     // 1

我们发现内嵌函数可以访问外层函数的变量,这样我们只要保证:

  • 外层函数无法访问
  • 内部变量只初始化一次
  • 外层函数暴露一个接口,该接口可以操作其内部变量
/**
 * 计数器的闭包实现
 * 通过立即执行的匿名函数 + 内部函数
 */
let counter2 = (function(){
    let count = 0;
    return function(){ return count += 1; }
})();

console.log(counter2());  // 1
console.log(counter2());  // 2
console.log(counter2());  // 3

这样立即执行函数只执行一次,同时又可以返回一个函数用来操作外层匿名函数的局部变量,这样就形成了一个 闭包

闭包是一种私有变量保护机制,在函数执行时形成私有作用域,保护里面的私有变量不受外接环境的影响。
直观的说就是形成一个不销毁的栈环境。

缺点

因为无法销毁,所以可能造成内存泄露!!

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注