闭包(closure)定义、使用场景及优势、注意事项

125 阅读2分钟

定义

闭包是一个函数及其词法环境的组合。这个词法环境包含了闭包被创建时的所有局部变量以及其他闭包。 简言之,闭包允许一个函数访问并操作函数外部的变量。在 JavaScript 中,每当一个函数被创建,闭包就会自动形成,连接内部函数与其外部作用域的变量。 例如

functio init() {
  const name = "M"; //name 是由 init 创建的局部变量。
  function displayName(){ //displayName() 是一个内部函数,是一个闭包。
    alert(name); //使用了父函数 init() 中声明的变量。
  }
  displayName();
}
init();

以上例子中,displayName()函数是一个闭包,因为它能够访问并使用其外部函数 init() 的局部变量 name。

使用场景及优势

  • 创建私有变量:JavaScript的函数作用域使得闭包成为实现私有变量和私有方法的强大工具,因为这些变量对于外部代码不能直接访问。
var counter = (function() {
  var privaterCounter = 0;
  function changeBy(val) {
    privaterCounter += val;
  }
  return {
    increment(){
      changeBy(1);
    },
    decrement(){
      changeBy(-1);
    },
    value:function(){
      return privaterCounter;
    }
  }
})();
  • 延长变量的生命周期:通常,函数内的局部变量在函数执行完会被销毁。闭包可以延长这些变量的生命周期,使其在函数执行完后仍能访问。
  • 柯里化(currying):闭包允许轻松地重用和应用函数,对于需要频繁调用相同参数的函数非常有用。例如,一个接受两个参数的函数 f(a, b) 通过柯里化后,会变成 f(a)(b) 的形式。
function add(a) {
    return function(b) {
        return a + b;
    };
}
const addFive = add(5);
console.log(addFive(2)); // 输出 7
  • 模拟私有方法:使用闭包可以模拟私有方法的功能,使某些函数和变量对外部代码不可见,增加了代码的封装性和安全性。

注意事项:

  • 性能考虑:闭包可能会导致比较高的内存使用,因为闭包中的变量不会在外部函数执行完后立即被销毁。不恰当的使用闭包可能会导致内存泄漏。
  • 方法定义:在创建对象或类时,应避免在构造器中定义方法。相反,这些方法应定义在对象的原型上,这样可避免每次实例化对象时都重新定义这些方法。