高阶函数
什么是高阶函数?
- 如果一个函数的参数是一个函数(回调函数就是高阶函数)
- 一个函数返回一个函数(当前这个函数也是一个高阶函数)
写代码时我们希望不要破坏原有逻辑而增加一些功能
对函数进行包装(装饰)切片编程(我们可以把核心抽离出来)包装上自己的内容,切片AOP。
const say = (...args) => { // 剩余运算符可以将参数转换成一个数组
console.log('说话',args); // '说话',['a','b','c']
}
希望在调用say方法之前做一些事
Function.prototype.before 给每个函数都扩展一些功能
Function.prototype.before = function(cb){
return () => { // 箭头含糊没有this指向
cb(); // 调用用户提前传入的before方法
// ...有两个作用:运算符 和 展开运算符
this(...args); // aplay也可以将数组依次传入
}
}
let newSay = say.before(function(){
console.log('before say');
});
newSay('a','b','c'); // 传递参数的问题
函数柯里化
什么叫函数柯里化,就是把一个函数的范围进行缩小,让函数变得更具体一些(让函数形成不销毁的堆内存 —— 闭包)
场景: 判断一个变量的类型
function(content,type){
return Object.prototype.toString.call(content) === `[object ${type}]`
}
let bool = checkType('hello','String');
checkType('hello','String');
柯里化函数写法
function checkType(type){
// 私有化,这个函数可以拿到上层函数的参数,会形成不销毁的堆内存 —— 闭包
return function(content){
return Object.prototype.toString.call(content) === `[object ${type}]`
}
}
let isString = checkType('String');
let isBoolean = checkType('Boolean');
let flag1 = isString('aaa');
let flag2 = isString('aaa');
console.log(flag1,flag2);
如何实现通用的函数柯里化,希望可以分开传递参数
const add = (a,b,c,d,e){
return a + b + c + d + e
}
const = curring = (fn,arr = [])=>{
let len = fn.length; // 长度指的是函数参数个数
return(...args)=>{ // 保存用户传入的参数
arr = [...arr,...args];
if(arr.length < len){ // 通过传递的参数,不停的判断是否达到函数执行参数个数
return curring(fn,arr);
}
return fn(...arr);
}
}
console.log(curring(add,[1,2]),(3),(4))
通用函数柯里化改造
function checkType(type,content){
return Object.prototype.toString.call(content) === `[object ${type}]`
}
let util = {};
['Number','String','Boolean'].forEach(item=>{
// 相当于将函数先调用用
util['is'+item] = curring(checkType)(item);
});
let r = util.isString('hello');
let b = util.isBoolean('true');
console.log(r,b);
`