闭包
闭包(Closure):函数和其周围的状态(词法环境)的引用捆绑在一起形成闭包。
- 可以在另一个作用域中调用一个函数的内部函数并访问到该函数的作用域中的成员。
//函数作为返回值
function makeFn(){
let msg='Hello function';
return function(){
console.log(msg);
}
}
const fn=makeFn();
fn();
外部对函数内部的成员有引用的时候,内部成员就不能释放。不然的话,makeFn()执行之后,makeFn()内部成员msg就会被释放。调用fn()的时候就是在调用内部函数,调用内部函数的时候会访问到msg。
在另一个作用域中可以调用makeFn()中定义的函数;当我们调用makeFn()内部函数的时候,可以访问到makeFn()中的内部成员。
延长了内部成员的作用范围。
//once 确保fn只被执行一次
function once(fn){
//用done标记fn是否被执行了
let done=false;
return function(){
//判断fn是否被执行
if(!done){
done=false;
return fn.apply(this,arguments);
}
}
}
//测试
let pay=once(function (money){
console.log(`支付:${money} RMB`);
})
//只会执行一次
pay (5);
pay (5);
pay (5);
pay (5);
- 闭包的本质:函数在执行的时候会放到一个执行栈上,当函数执行完毕之后会从执行栈上移除,但是堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员。
闭包案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 生成求次方的函数
// Math.pow(3,2);
function makePower(power){
return function(number){
return Math.pow(number,power);
}
}
// 求平方
let power2=makePower(2);
// 求立方
let power3=makePower(3);
// 测试
console.log(power2(4));
console.log(power3(2));
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 工资:级别,绩效工资
// getSalary(12000,2000);
// 为不同级别的计算工资
function makeSalary(base){
return function(performance){
return base+performance;
}
}
let salaryLevel1=makeSalary(12000);
let salaryLevel2=makeSalary(15000);
console.log(salaryLevel1());
</script>
</body>
</html>