简介
柯里化,英语:Currying,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。 ——维基百科
>
示例
// 普通的add函数
function add(x, y) {
return x + y
}
// currying后
function curryingAdd(x) {
return function (y) {
return x + y
}
}
curryingAdd(1)(2) // 3
作用
1. 参数复用
function curryingCheck(reg) {
return function(txt) {
return reg.test(txt)
}
}
var hasDigit = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasDigit('test1') // true
hasDigit('test') // false
hasLetter('123') // false
2. 提前确认
const on = (document, element, event, handler) => {
if (document.addEventListener) {
element.addEventListener(event, handler, false);
}
else {
element.attachEvent('on' + event, handler);
}
};
// 提前确认注册事件的方法,就不用在每次调用on时候确认
const on = (doc => {
return doc.addEventListener
? (element, event, handler) => {
element.addEventListener(event, handler, false);
}
: (element, event, handler) => {
element.attachEvent('on' + event, handler);
}
})(document);
3. 延迟运行
function add(...args) {
return args.reduce((prev, current) => prev + current);
}
add(1, 2, 3, 4);
function curry(fn){
let args = [];
return function cb() {
if(arguments.length < 1) {
return fn(...args);
}
else {
args = [...args,...arguments]
return cb;
}
}
}
cAdd = curry(add);
cAdd(1)(2)(3)(4)();
延迟执行实际上就是当我们调用这个方法时,不会立即执行,或者说在参数符合规定的时候才会执行我们真正想执行的内容。
实现
1. 通用实现
function currying(fn, ...rest) {
return function(...args) {
return fn(...rest, ...args);
}
}
function sum(a, b, c, d) {
console.log(a + b + c + d)
}
const add = currying(sum, 1, 2);
add(3, 4);
// 执行结果
10
2. 递归实现
function add(a, b, c, d) {
console.log(a + b + c + d);
}
const curriedAdd = currying(add);
curriedAdd(1)(2)(3)(4); // 10
curriedAdd(1, 2, 3)(4); // 10
curriedAdd(1, 2, 3, 4); // 10
function currying(fn) {
const len = fn.length;
let _args = [];
const curry = () => {
return function (...args) {
// 如果参数攒够了就执行
if (_args.length + args.length >= len) {
const result = fn(..._args, ...args);
// 执行完重置_args
_args = [];
return result;
}
// 参数不够就继续攒
else {
_args = [..._args, ...args];
return curry();
}
}
}
return curry();
}
经典面试题
// 实现一个add方法,使计算结果能够满足如下预期:
// add(1)(2)(3) == 6 // true
// add(1, 2, 3)(4) == 10 // true
// add(1)(2)(3)(4)(5) == 15 // true
function add() {
// 第一次执行时,定义一个数组专门用来存储所有的参数
var _args = Array.prototype.slice.call(arguments);
// 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
var _adder = function() {
_args.push(...arguments);
return _adder;
};
// 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
_adder.toString = function () {
return _args.reduce(function (a, b) {
return a + b;
});
}
return _adder;
}