函数柯里化

61 阅读1分钟

函数柯里化: 接收一部分参数,返回一个函数接收剩余参数,接收足够参数后,执行原函数。

虽然开发中没用到过,但是还是记录一下,或许面试官会问呢

function curry(fn) {
    // 其上下文入口,可能是tag1, 也可能是tag2
    // 拿到第一个参数fn以外的剩余参数,因为要保存这个参数
    let preArgs = Array.prototype.slice.call(arguments, 1)
    
    // 返回一个函数,fn调用的时候在global执行,而不在自身的词法作用域curry里执行,所以就形成了一个闭包
    return function() {
        // 拿到curry的arg和回调函数的ags做拼接
        let newArgs = [...preArgs, ...arguments]
        if(newArgs.length >= fn.length ) {
            return fn.apply(this, newArgs)
        } else {
            // 参数不足够就保存之前的参数,等待足够后再执行函数
            return curry.call(this, fn, ...newArgs) // tag2
        }
    }
}

fn = curry(function(a, b, c, d) {
    return a+b+c+d 
})

fn(1,2)(3)(4)

fn1 = curry(function(a, b, c, d) { // tag1
    return a+b+c+d 
}, 1,2,3)
fn1(4)

其实还有看到过toString方法,但是感觉不太好。一般情况下也不提倡修改对象本身的toString属性,其做隐式类型转换的时候可能会造成不好的影响。

toStirng换成__defineGetter__试试

// 实现一个不限参数的累加
// 原理和柯里化相似
function add() {
    let preArgs = [...arguments]
    function sum () {
        let newArgs = [...preArgs, ...arguments]
        return add.apply(this, newArgs)
    }
    sum.__defineGetter__('value', () => {
        return preArgs.reduce((a,b) => a + b)
    }) 
    return sum 
}

let x = add(1,2,3)(4,5)(6)(7)
// 与其隐式显示调用toString方法,不如显示调用获取值
console.log(x.value)