闭包学习笔记| 青训营笔记

77 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天

JavaScript闭包是JavaScript语言中一个非常重要的概念,也是许多初学者难以理解的概念。

一、概念

闭包是指函数和其相关的变量在定义时形成的一个作用域,该作用域可以访问该函数中的变量,并且在函数执行完毕后依然可以访问这些变量。

二、工作原理

当一个函数内部定义了另一个函数时,如果内部函数使用了外部函数的变量,那么这个内部函数就形成了一个闭包。闭包会将内部函数所使用的外部变量保存在内存中,使得这些变量可以在内部函数执行后继续存在。

闭包的工作原理可以简单地用下面的代码来说明:

function outerFunction() {
  let outerVariable = "Hello, world!";

  function innerFunction() {
    console.log(outerVariable);
  }

  return innerFunction;
}

let closure = outerFunction();
closure(); // Output: "Hello, world!"

在上面的代码中,outerFunction()定义了一个变量outerVariable,并且内部定义了一个函数innerFunction(),该函数使用了outerVariable变量。outerFunction()将innerFunction()作为返回值返回,并且保存在变量closure中。最后,执行closure()函数,输出"Hello, world!"。由于closure()是outerFunction()中定义的innerFunction(),因此它可以访问outerVariable变量,这就是闭包的工作原理。

三、使用场景

闭包在JavaScript中有许多使用场景,下面介绍一些常见的场景:

将变量私有化&避免全局变量污染

通过闭包,可以将某些变量私有化,使得这些变量只能被特定的函数所访问。这可以有效地避免变量被外部函数意外修改的问题同时避免全局变量污染的问题

function createCounter() {
  let count = 0;

  return function() {
    count++
    console.log(count);
  };
}

let counter = createCounter();
counter(); // Output: 1
counter(); // Output: 2

在上面的代码中,createCounter()函数返回了一个函数,该函数可以访问变量count。由于count只能在createCounter()中被访问,因此它被私有化了,外部函数无法直接访问count变量。

保存函数状态

闭包还可以用于保存函数的状态,使得函数在多次调用时可以继续保留之前的状态。

function createAdder(x) {
  return function(y) {
    return x + y;
  };
}

let add5 = createAdder(5);
console.log(add5(2)); // Output: 7
console.log(add5(3)); // Output: 8

在上面的代码中,createAdder()函数返回一个函数,该函数可以访问参数x,并返回一个内部函数。该内部函数可以访问参数y,并将x和y相加返回结果。通过调用createAdder()函数并传入参数5,可以创建一个新的函数add5,该函数可以将5与其传入的参数相加。由于add5使用了createAdder()内部的变量x,因此在多次调用add5时,x的值被保存下来,使得add5可以保留之前的状态并继续进行计算。

避免全局变量污染

闭包还可以用于避免全局变量污染的问题。通过将变量定义在闭包内部,可以避免这些变量被外部函数意外修改。

(function() {
  let message = "Hello, world!";

  function showMessage() {
    console.log(message);
  }

  showMessage();
})();

在上面的代码中,使用立即调用函数表达式(IIFE)创建一个闭包,并将变量message定义在该闭包内部。由于message只能在闭包内部被访问,因此可以避免全局变量污染的问题。

四、注意事项

虽然闭包在JavaScript中非常有用,但是需要注意一些潜在的问题。使用闭包时需要注意以下几点:

  1. 避免内存泄漏

由于闭包会将变量保存在内存中,如果不恰当地使用闭包,可能会导致内存泄漏。当闭包保存了大量的变量时,可能会占用大量的内存。因此,在使用闭包时需要谨慎地考虑变量的使用和释放。

  1. 不要滥用闭包

尽管闭包在某些情况下非常有用,但是滥用闭包会导致代码难以维护和调试。在使用闭包时需要权衡利弊,确保其使用场景符合实际需求。

  1. 注意变量作用域

由于闭包会创建一个新的作用域,因此需要注意变量的作用域。在使用闭包时需要考虑变量的作用域,并确保其符合实际需求。