JavaScript函数柯里化及简单题目
1. 函数柯里化
柯里化是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回一个新函数,这个新函数能够接受原函数的参数。下面可以通过例子来帮助理解。
// 简单的柯里化
function adder(num) {
return function(x) {
return num + x;
}
}
var add5 = adder(5);
var add6 = adder(6);
console.log(add5(1)); // 6
console.log(add6(1)); // 7
柯里化在DOM的回调中非常有用。因为柯里化可以将分别多次传入的参数储存起来最后做同一处理。
通俗点说柯里化就是利用已有的函数, 再创建一个动态的函数,该动态函数内部还是通过已有的函数来发生作用,只是传入更多的参数来简化函数的参数方面的调用。
function curry(fn) {
var args = [].slice.call(arguments, 1);
return function() {
return fn.apply(null, args.concat([].slice.call(arguments, 0)));
}
}
function add(numl, num2} {
return numl + num2;
}
var newAdd = curry(add, 5);
alert (newAdd (6)); / /11
在curry 函数的内部,私有变量args 相当千一个存储器,用来暂时存储在调用curry 函数时所传递的参数值,这样再跟后面动态创建函数调用时的参数合并并执行,就会得到一样的效果。
函数柯里化的基本方法和函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,当函数被调用时,返回函数还需要设置一些传入的参数。
// 返回一个新函数,参数已提前内定
function bind(fn, context) {
var args = Array.prototype.slice.call(arguments, 2);
return function() {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(context, finalArgs);
}
}
// 在Function.prototype就操存在有bind方法,函数可以直接调用,
// 语法:function.bind(thisArg[, arg1[, arg2[, ...]]]),与上述bind方法作用类似
创建柯里化函数的通用方式是:
function curry(fn) {
var args = Array.prototype.slice.call(argurnents, 1);
return function() {
var innerArgs = Array.prototype.slice.call(argurnents);
var finalArgs = args.concat(innerArgs);
retrun fn.apply(null, finalArgs);
}
}
curry 函数的主要功能就是将被返回的函数的参数进行排序。为了获取第一个参数后的所有参数,在arguments 对象上调用slice()方法,并传入参数1 表示被返回的数组的第一个元素应该是第二个参数。
2. 利用函数柯里化的简单题目
-
实现一个函数add,使得add(3)(4)(5)() = 12,add(3)(4, 5)(6)() = 18
-
代码实现:
add.args = null // 静态变量args function add() { // 第一次都没有传参数,直接结束 if(arguments.length === 0) return null // 将第一次传入的参数保存起来 add.args = Array.from(arguments) // 返回一个函数 return function() { if (arguments.length === 0) { // 调用时没有再传参数了,将之前收集的参数统一处理,返回结果 const result = add.args.reduce((a, b) => { return a + b }) return result } else { // 调用时继续传入参数,将参数保存到静态变量中,返回本身函数准备接受下一次调用 add.args = [...add.args, ...Array.from(arguments)] return arguments.callee } } }