函数柯里化(包括实现方法以及相关优劣势)

函数柯里化(概念)

函数柯里化,又可以被称作部分求值。此类函数,在传入部分的值后,并不会立刻求值,而是返回一个函数,并且在参数未满足条件时(参数个数未达标或未传入结束标识符),会将传入的值存储在形成的闭包中,等待下一次调用。

一个函数,在经过柯里化后,可以不需要将值一次性传入。例如:

// 仅作为示例,具体使用参照下文中的代码
// 柯里化前
add(1,2,3)
// 柯里化后
add(1,2)(3)

优缺点

优点:

  • 延迟计算,当参数未齐或者未传入结束标识符时,仍返回函数
  • 参数复用,利用闭包的特性,将第一个传入的参数存入闭包空间,不会被销毁。

缺点:

  • 容易造成内存泄漏,也是由闭包的特性造成
  • 性能不高,因为使用了递归的方式
  • 函数进行了嵌套,新人不易理解

经典面试题

函数柯里化,在前端面试八股文中,是比较经典的一个面试题。例如:

实现一个add函数,实现以下功能
add(1,2,3)
add(1)(2)(3)
add(1,2)(3)
add(1,2,3,4)

此类题目,部分面试官会给出限定的参数个数,但也有部分面试官不会给出指定的参数个数。

固定参数个数

const curry = function(fn){
	let len = fn.length // 获取函数的参数个数
    return function t(){
    	let innerLen = arguments.length
    	// 因为arguments只是类数组,需要先将其转化为数组
        const args = Array.prototype.slice.call(arguments)
        if(innerLen>=length){
        	// 参数个数达到要求,执行fn函数
            return fn.apply(undefined,args)
        } else{
        	// 参数个数未达要求,递归执行,继续返回函数
            return function(){
            	// 获取下一次调用时传入的参数,与之前的参数进行拼接后,重新调用t函数
                const innerArgs = Array.prototype.slice.call(arguments)
                const allArgs = args.concat(innerArgs)
                return t.apply(undefined,allArgs)
            }
        }
    }
}

function add(num1,num2,num3){
    return num1+num2+num3
}

let finalFun = curry(add)

let res1 = finalFun(1)(2)(3) // 6
let res2 = finalFun(1)(2,3) // 6
let res3 = finalFun(1,2)(3) // 6

无固定参数个数,以标识符作为结尾

const curry = function(fn){
    return function t(){
    	// 因为arguments只是类数组,需要先将其转化为数组
        const args = Array.prototype.slice.call(arguments)
        if(args.includes("end")){
            return fn.apply(undefined,args)
        } else{
            return function(){
                const innerArgs = Array.prototype.slice.call(arguments)
                const allArgs = args.concat(innerArgs)
                return t.apply(undefined,allArgs)
            }
        }
    }
}

function add(){
	// 因为参数个数不固定,所以需要从arguments中获取
    let args = Array.prototype.slice.call(arguments)
    // Array.findIndex,传入一个方法进行判断,当方法返回true时,findIndex停止执行,直接返回符合条件的下标
    let endIndex = args.findIndex((item) => {
        return item === 'end'
    })
    let sum = 0
    for(let index = 0;index<endIndex;index++){
        sum += args[index]
    }
    return sum
}

let finalFun = curry(add)

let res1 = finalFun(1)(2)('end') // 3
let res2 = finalFun(1)(2,3)('end') // 6
let res3 = finalFun(1)(2,3)(4,'end') // 10
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值