你了解闭包?你平常用闭包的场景有哪些?
闭包的定义?
-
闭包是指那些能够访问自由变量的函数
-
自由变量是指函数中使用的,但即不是函数参数也不是函数局部变量的变量
-
- 从理论角度:所有的函数都有可能是闭包,函数中去访问全局变量就相当于是在访问自由变量
-
- 从实践角度:
- 2.1 即使创建它的上下文已经被销毁了,他仍然存在,(内部函数从父函数中返回)
- 2.2 代码引用了自由变量
- 从实践角度:
应用场景
-
- 柯里化函数 避免频繁调用具有相同参数的函数,同时能够轻松的复用 其实就是封装一个高阶函数
function getArea(width, height) {
return width * height;
}
const area1 = getArea(10, 29);
const area2 = getArea(10, 20);
// 第一个参数保持不变,可以用柯里化函数
function getArea(width) {
return height => {
return width * height;
}
}
const getTenWidthArea = getArea(10);
const area1 = getTenWidthArea(29);
-
- 使用闭包实现私有方法/变量
- 模块
-
现代化的打包方式,最终就是每个模块的代码都是相互独立的
-
- 匿名的自执行函数
var fnOne = (fuction() { var num = 0; return function() { num++; return num; } })();
- 匿名的自执行函数
-
- 缓存一些结果
外部函数中创建一个数组,闭包函数可以获取或者修改这个数组的值,延长了变量的生命周期
function funParent() {
let meno = [];
function funOne(i) {
meno.push(i);
console.log(meno);
}
return funOne;
}
总结
- 创建自由变量
- 延长变量的生命周期
代码题
// 实现一个compose函数,用法如下:
function fn1(x) {
return x + 1;
}
function fn2(x) {
return x + 2;
}
function fn3(x) {
return x + 3;
}
function fn4(x) {
return x + 4;
}
const a1 = compose(fn1, fn2, fn3, fn4);
console.log(a1(1)); // 1+2+3+4+1 = 11
// 解答
function compose() {
const argsArr = [...arguments];
return (x) => {
return argsArr.reduce((pre, cur) => cur(pre), x);
}
}
// 柯里化
function currying(fn, ...args) {
const originFnLength = fn.length;
let allArgs = [...args];
const resFn = (...fnArgs) => {
allArgs = [...allArgs, ...fnArgs];
if(originFnLength === allArgs.length) {
return fn(...allArgs);
} else {
return resFn;
}
}
return resFn;
}
const add = (a, b, c) => a+b+c;
const a1 = currying(add, 1);
const a2 = a1(2);
const a3 = a2(3);
/**
题目需求,实现koa compose
*/
let middleware = [];
middleware.push((next) => {
console.log(1);
next();
console.log(1.1);
});
middleware.push((next) => {
console.log(2);
next();
console.log(2.1);
});
middleware.push((next) => {
console.log(3);
next();
console.log(3.1);
});
let fn = compose(middleware);
fn();
function compose(middleware) {
const copyMiddleware = [...middleware];
let index = 0;
const fn = () => {
if(index >= copyMiddleware.length) {
return;
}
const curMiddleware = copyMiddleware[index];
index++;
return curMiddleware(fn);
}
return fn;
}
/*
1
2
3
3.1
2.1
1.2