面试题之一:柯里化

323 阅读2分钟

1. 一道实现函数柯里化的面试题

题目

// 实现一个函数add, 满足以下两种调用方式,其结果都为6:
add(1, 2, 3)
add(1)(2)(3)

解法

function add() {
    var args = [...arguments] // push第一次调用add函数的参数
    var temp = function() {
        // 将每一次调用时的参数都push进 args 变量中
        args.push(...arguments)
        // 返回temp函数自身,即第二次调用add函数以及之后的每一次调用都是在调用temp函数
        return temp
    }
    temp.toString = function() {
        // 由于调用无论调用add函数多少次最终都是返回temp函数本身,最终的temp函数并未执行,
        当在console中打印该temp函数时,函数会隐式转换调用toString()方法,因此可以改写temp函数的toString()方法,将args数组累加返回
        return args.reduce((acc, x) => acc += x, 0)
    }
    return temp // 第一次调用add函数时返回temp函数
}

2. 柯里化实现 Function.prototype.bind() 函数

函数柯里化是指传入部分参数给一个函数,并返回一个新函数的一个过程。Javascript 的 Function.prototype.bind() 函数的概念在MDN中的解释为:

bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。

bind()函数可以显示绑定函数的this值,并返回一个新的函数,可以借助柯里化和显示绑定函数this值的apply()函数来实现。

Function.prototype._bind = function () {
    var fn = this  // 原函数自身
    var context = [].shift.call(arguments) // 需要绑定的this上下文,即为arguments里的第一个参数
    var args = [].slice.call(arguments)   // 剩余的参数转为数组
    return function () {
        // 绑定this值,并将调用_bind()函数是传入的参数和调用新函数时传入的参数合并
        return fn.apply(context, args.concat([].slice.call(arguments)))
    }
}

console 中验证该函数: