JavaScript闭包
目录
目标
语法结构
应用场景
数据隐藏和封装
函数柯里化
异步延迟回调
目标
了解闭包的语法结构与应用场景。了解Python的同学可以对比一下我之前写的Python闭包文章,两者非常相似。
语法结构
以下两种书写方式是等价的。
//方式一
function outer(){
function inner(){
}
return inner
}
//方式二
function outer(){
return function inner(){
}
}
应用场景
数据隐藏和封装
需求
在环境监测项目中,我们需要定期获取气象数据(比如:降雨量)。这些数据十分敏感,我们可以使用闭包来封装和隐藏这些数据,确保它们只能通过合法的方式进行访问或修改。
function create_rain_sensor(init_value){
function update_init_value(){
if (init_value<0){
init_value=null
}else{
//四舍五入保留2位小数
init_value = Number(init_value.toFixed(2));
}
console.log(init_value)
}
return update_init_value
}
// 创建雨量传感器并初始化为 -1
const rainSensor = create_rain_sensor(-1);
rainSensor(); // 输出 null
// 创建雨量传感器并初始化为 12.3456
const rainSensor2 = create_rain_sensor(12.3456);
rainSensor2(); // 输出 12.35
函数柯里化
柯里化是将多个参数的函数转换为单一参数的函数,并且返回每个单一参数函数,直到所有参数都被提供。这对于延迟执行和函数组合非常有用。
需求一
返回两个数字相乘的结果。
function outer(a){
return function inner(b){
return a*b
}
}
const inner=outer(2)
//避免重复传递参数。
console.log(inner(6))
console.log(inner(7))
console.log(inner(8))
需求二
绑定li的点击事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书馆</title>
</head>
<body>
<h1>小说</h1>
<ul>
<li>凡人修仙传</li>
<li>诛仙</li>
<li>鹿鼎记</li>
<li>天龙八部</li>
</ul>
<script>
let allLi=document.querySelectorAll("li")
for(var i=0;i<allLi.length;i++){
allLi[i].onclick=(
function(index){
return function(){
alert("点击了第"+index+"个li标签。")
}
}
)(i)
}
</script>
</body>
</html>
异步延迟回调
异步执行过程中可能会导致变量被污染,比如下面的代码,每次都输出相同的结果:
//这里先不考虑使用let创建变量。
for (var i = 1; i <= 3; i++) {
setTimeout(function () {
//第 4 次执行
console.log(`第 ${i} 次执行`);
}, i * 1000);
}
需求
使用闭包将上述案例修改正确。
for (var j = 0; j <= 3; j++) {
(function (index) {
setTimeout(function () {
console.log(`第 ${index} 次执行`);
}, index * 1000);
})(j);
}