返回

闭包 - 理解与应用

前端

闭包剖析

闭包,全称词法闭包,是函数内部可以访问外部变量的特性。它是在函数被定义时所决定的,而不是在函数被调用时。

闭包的妙用

自由变量(最简单)

最为经典,也是最简单的例子,嵌套函数中访问其上级作用域的变量。

// 上级作用域
function sum(a, b) {
  var c = a + b;
  // 嵌套函数
  function add() {
    return c;
  }
  return add;
}
// 调起嵌套函数,即闭包
var result = sum(1, 2)();
console.log(result); // 3

函数工厂(进阶)

闭包的另一大妙用,就是函数工厂。通过闭包,我们可以根据需求动态创建函数。

// 闭包工厂,创建加法函数
function adder(base) {
  return function(num) {
    return base + num;
  };
}

// 创建加 10 的函数
var add10 = adder(10);
// 创建加 20 的函数
var add20 = adder(20);

// 调用函数
console.log(add10(5)); // 15
console.log(add20(5)); // 25

私有变量(高阶)

闭包的另一个妙用,就是私有变量。通过闭包,我们可以在函数内部声明变量,而不被外部访问,从而实现封装。

// 闭包封装私有变量
function counter() {
  var count = 0;
  return function() {
    return count++;
  };
}

// 创建计数器
var counter1 = counter();
var counter2 = counter();

// 使用计数器
console.log(counter1()); // 0
console.log(counter1()); // 1
console.log(counter1()); // 2
console.log(counter2()); // 0
console.log(counter2()); // 1

闭包的陷阱

闭包虽然强大,但也存在一些陷阱,需要特别注意。

内存泄漏

闭包可能会导致内存泄漏,因为闭包函数内部保存了对外部变量的引用,即使外部变量已经不再使用,但闭包函数仍然可以访问到该变量,从而导致该变量无法被回收。

// 闭包导致内存泄漏
function createFunction() {
  var list = [];
  for (var i = 0; i < 10; i++) {
    list.push(function() {
      console.log(i);
    });
  }
  return list;
}

// 创建闭包函数列表
var functions = createFunction();

// 释放对列表的引用
list = null;

// 调用闭包函数
functions[5](); // 10

// 内存泄漏,变量 i 无法被回收

闭包陷阱

闭包陷阱是指在闭包函数内部访问外部变量时,外部变量可能已经发生变化,从而导致闭包函数产生错误的结果。

// 闭包陷阱
function outer() {
  var a = 1;
  function inner() {
    console.log(a);
  }
  return inner;
}

// 创建闭包函数
var innerFunc = outer();

// 修改外部变量
a = 2;

// 调用闭包函数,输出错误的结果
innerFunc(); // 1

// 预期结果应该是 2

结语

闭包是一个强大的工具,但它也存在一些陷阱,需要特别注意。掌握闭包的妙用与陷阱,可以在面试中脱颖而出,在开发中游刃有余。作为一名技术博客创作专家,我以独树一帜的观点展现事物,通过剖析和阐述,带领读者深入理解闭包,从而在编程世界里披荆斩棘,所向披靡。