简介
柯里化,英语: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') // truehasDigit('test') // falsehasLetter('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); // 10curriedAdd(1, 2, 3)(4); // 10curriedAdd(1, 2, 3, 4); // 10function 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 // truefunction 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;}
