官方定义:闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。
人话:就是在函数内部访问上层函数作用于内的变量。
闭包的形成
function fun1() {
let str = '123';
// 此处返回函数,且函数使用上层作用域的变量,在使用时就会形成闭包
return () => {
console.log(str);
}
}
const f1 = fun1();
f1();
闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。
闭包的用途
解决for循环中的变量共用问题
// 此代码会打印5次: 5 4
for(var i = 0; i < 5; i++) {
var ii = i;
setTimeout(() => {
console.log(i, ii)
}, 200)
}
因为var声明的变量会做变量提升,所以在定时器执行完毕后,i和ii的值都已经在循环结束时固定。可以使用闭包解决此问题。
for(var i = 0; i < 5; i++) {
(function () {
var ii = i;
setTimeout(() => {
console.log(i, ii)
}, 200)
}())
}
输出结果为:5 0、5 1、5 2、5 3、5 4。
可以看到ii已经在闭包闭包函数执行时声明成了匿名函数内的局部变量,定时器内部函数再调用时就没有问题了。
当然这种问题可以使用es6的let和const解决,不用那么麻烦。
节流防抖函数中的应用
实现类似add(1,2)(3)(4)...()
function add(...args: number[]) {
let result: number[] = args;
function _add(...args2: number[]): any {
if(args2.length) {
result = result.concat(args2);
return _add
} else {
return result.reduce((p, r) => r + p, 0)
}
}
return _add;
}
// 输出28
console.log(add(1,2,3)(4,5,6)(7)())
其他
如react函数组件......