JavaScript 中的闭包是什么?
我最近购买并阅读了 Kyle Simpson 的《 You Don't Know JS Yet》这本书,觉得非常值得一读。虽然我已经从事 JS 开发多年,但通过阅读这本书,我仍然学到了很多新知识(我并未接受任何与本书相关的机构或个人的赞助——我只是真心喜欢这本书,所以才推荐它)。
其中之一就是“了结”——这个词我听过几次,但一直没弄明白它到底是什么意思。我觉得凯尔·辛普森的定义很难被超越:
闭包是指函数记住并继续访问其作用域之外的变量,即使该函数在不同的作用域中执行也是如此。
那么,那会是什么样子呢?
一些闭包的例子
你可能之前已经用过闭包,只是自己没有意识到而已。例如:
function doAsyncTask(successMsg) {
someAsyncTask().then(() => {
console.log(`I remembered your variable! ${successMsg}`);
});
}
getSuperImporantInfo('Hooray!');
// Some time later...
// I remembered your variable! Hooray!
执行完毕后someAsyncTask,它会打印出successMsg传递给它的变量doAsyncTask。someAsyncTask执行可能需要几秒钟甚至几分钟,但传递给它的回调函数会then“记住”这个successMsg变量。我们称回调函数对这个变量是“封闭的” successMsg。
我一直都做类似的事情,只是我不知道自己用了“闭合”这个词!
假设你想创建一个计数器函数。每次调用该函数时,它都会返回上一次返回的数字之后的下一个数字。你可以使用闭包来“记住”上次返回的数字。
function createCounter() {
let count = 0;
return () => count++;
}
const inc = createCounter();
inc();
// 0
inc();
// 1
inc();
// 2
createCounter返回一个可以访问该count变量的匿名函数。返回的函数对变量createCounter是“封闭的” count。我们甚至可以创建多个递增函数,每个函数都将拥有自己的变量副本count。
const inc1 = createCounter();
const inc2 = createCounter();
inc1();
// 0
inc2();
// 0
inc1();
// 1
inc1();
// 2
inc2();
// 1
这些例子虽然简单,但我以前确实需要编写类似的计数器函数。在了解闭包之前,我会创建对整个模块可见的变量,然后在计数器函数中递增这些变量。现在我知道有更好的方法,无需污染模块的作用域。
就是这样!你还能想到哪些可以利用闭包效应的例子呢?
文章来源:https://dev.to/brettfishy/what-is-closure-in-javascript-579f