持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情
JS的函数柯里化理解
1、什么是柯里化?
柯里化(currying):是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术;
实现一个简单的例子:
// 普通函数
function count(a:number,b:number){
• return a + b;
}
// 柯里化后
function curryingCount(a:number){
• return function(b:number){
• return a + b;
• }
}
console.log(count(2,2))
console.log(curryingCount(2)(2));
看完这个简单的例子,你可能会觉得这样封装反而没之前方便了,那么请看下面一个例子
// 普通函数封装
function counts(a:string,b:string){
return a + b;
}
console.log(counts('小明','吃饭'));
console.log(counts('小明','睡觉'));
console.log(counts('小明','上学'));
/**
-
小明吃饭
小明睡觉
小明上学
*/
// 从这三个函数调用可以发现,第一个参数重复了,普通函数封装又不得不每次都带上这个参数
// 柯里化后
function curringCounts(a:string){
return function(b:string){
return a + b;
}
}
let names = curringCounts('小明')
let namet = curringCounts('老王')
console.log(names('笑哈哈'));
console.log(names('算数学'));
console.log(namet('住隔壁'));
/**
-
小明笑哈哈
小明算数学
老王住隔壁
*/
这个就是柯里化的优点之一,参数复用(利用闭包的原理,让前面传输的参数一直存在)
js的bind函数的实现机制就是柯里化的封装
Function.prototype.bind = function (context){
• var that = this
• var args = Array.prototype.slice.call(arguments,1)
• return function(){
• return that.apply(context,args)
• }
}
这也是柯里化的优点之一:延迟运行(利用闭包将函数的定义和执行环境分开)
接下来的一个例子
var on = function(isSupport:any, element:any, event:any, handler:any){
isSupport = isSupport || document.addEventListener
if (isSupport){
return element.addEventListener(event,handler,false);
}else{
return element.attachEvent('on'+event,handler)
}
}
这是柯里化的优点之一:提前确认(利用柯里化特性对某些全局方法进行改写,就是提前确定会走哪个方法,避免每次都进行判断)
通用封装方法
var currying = function (fn:any){
// args 获取第一个方法内全部参数
var args = Array.prototype.slice.call(arguments,1)
return function(){
var newArgs = args.concat(Array.prototype.slice.call(arguments))
return fn.apply(this,newArgs)
}
}
支持多参数传递
function progressCurring(fn:any,args:any){
var that = this
var len = fn.length;
var args = args || []
return function(){
var _args = Array.prototype.slice.call(arguments)
Array.prototype.push.apply(args,_args);
// 如果参数个数小于最初的fn.length,则递归调用,继续收集参数
if(_args.length<len){
return progressCurring.call(that,fn,_args);
}
return fn.apply(this,_args)
}
}
经典面试题
function add() {
const _args = [...arguments];
function fn() {
_args.push(...arguments);
return fn;
}
fn.toString = function() {
return _args.reduce((sum, cur) => sum + cur);
}
return fn;
}
console.log(add(1,2,3)(4));