什么是JavaScript闭包?

闭包是JavaScript中经常出现的一个概念,尤其在面试中经常被提及。虽然听起来很复杂,但实际上并不那么难理解,而且无论你的专业水平如何,你可能已经在你的代码中使用过它们。让我们从闭包是什么开始:

当一个函数访问在其外部定义的变量时,就形成了一个闭包。

这听起来并不太复杂。让我们看一个例子:

const items = [
  { id: 1, title: 'First' },
  { id: 2, title: 'Second' },
  { id: 3, title: 'Final' }
];
const matcher = /^F/;
const filteringFn = x => matcher.test(x.title);
items.filter(filteringFn); // [{ id: 1, title: 'First' }, { id: 3, title: 'Final' }]

上面的例子定义了一些数据用于操作,一个用于匹配的正则表达式,以及一个函数filteringFn,然后将其作为过滤函数在Array.prototype.filter()中使用。如果你仔细观察filteringFn,你会注意到它使用了一个在其外部定义的变量,即matcher。这就是一个闭包。

让我们看另一个更复杂的例子:

const initCounter = (start = 0) => {
  let value = start;
  return {
    get: () => value,
    increment: () => ++value,
    decrement: () => --value,
    reset: () => value = start
  };
}

const counter = initCounter(5);
counter.get(); // 5
counter.increment(); // 6
counter.increment(); // 7
counter.decrement(); // 6
counter.reset(); // 5

在这个例子中,我们定义了一个函数initCounter,它返回一个对象,该对象的属性是函数。返回的对象的所有属性都使用闭包以某种方式操作initCountervalue变量。这种方法的明显好处是,如果你想通过initCounter定义多个计数器,你不需要在各个地方创建多个value实例,而是通过闭包安全地封装在返回的对象中。

使用闭包,就像上面的示例一样,可以帮助使您的代码更易用和可维护,同时允许您根据需要分离关注点并创建抽象。