在计算机科学中,柯里化(Currying)是一种技术(技巧),可以把原本接受 n 个参数的函数A,转换成只接收一个参数的函数B(B中的惟一参数,就是A的多个参数中的 第一个 参数)。面试
而后新函数B返回的,仍是一个函数,记为C(注意原A中返回的不必定是啥)。这个C函数又只能接收一个参数(即为A函数的 第二个 参数)......依次不断往复,直到返回一个接收A的第 n 个参数的函数F,F中判断这是最后一个函数了,执行,而后返回最终的值。数组
很绕口,看个例子:浏览器
// 咱们想要实现一个把参数相加,返回和的函数
function adder(a, b) {
return a + b;
}
adder(4,6);
// 结果为:10
复制代码
固然也能够这样写(非柯里化)bash
function adder() {
var sum = 0;
for(var i=0;i<arguments.length;i++)
sum += arguments[i];
return sum;
}
adder(4,6);
// 10
复制代码
用柯里化实现闭包
var adder = function(num) {
var n = num; // 对应的为参数4
return function(y) {
return n + y; // y为6 返回 4+6
}
}
adder(4)(6) // 10
复制代码
从上面能够看到,原本adder是传2个参数adder(4, 6),柯里化的方式后,就成为了adder(4)(6),即每次接受一个参数并放回一个函数,而后链式的执行。。。app
能够看到,adder函数中有着内部函数,内部函数一直引用着n,这就造成了一个闭包,因此柯里化是闭包的应用之一,面试时直接能够答~~~函数
从上面能够大概了解了,柯里化就是,post
把原来的函数 adder(3,5,6,7,8,9) ==> adder(3)(5)(6)(7)(8)(9)()ui
注意:最后一次调用没有参数(),因此adder中能够经过判断是否有参数,去判断我是要继续相加,仍是返回求和值了this
或是这样也能够
adder(3)
adder(5,6,7)
adder(8,9)
adder() // 无参数时返回和
复制代码
那么这么作的好处是什么呢?
因此咱们能够在写一个函数的时候,用柯里化的思想去写;可是咱们也能够对任何一个原有的函数,将他柯里化了,变成柯里化的思想与形式,看思路~
例:
一个原有的函数
// 不知道这test函数是啥功能,不用管他是干啥的,但很显然不是简单的求和,
// 因此你不能继续用 循环 arguments 了。。。
function test(name, id, num, score, height) {
}
复制代码
将他柯里化,就是要将他
test("chen", 45, 789, 284.2, 178) ==> test2("chen")(45)(789)(284.2)(178)()
其中test2就是通过柯里化包装后的test
包装的思想是
通用封装代码以下,必定要搞懂!
若是仍是没以为有啥用,看两个实际的例子
1. 浏览器事件
还记得事件要区分IE和非IE不了
var addEvent = function(el, type, fn, capture) {
if(window.addEventListener) {
el.addEventListener(type, function(e) {
fn.call(el, e)
}, capture)
} else {
el.attachEvent('on'+type, function(e) {
fn.call(el, e)
})
}
}
复制代码
也就是说,咱们会调用addEvent,可是每次的话都得执行内部的if...else....
因此能够用柯里化,改为
var curEvent = (function() {
if(window.addEventListener) {
return function(el, sType, fn, capture) { // return funtion
el.addEventListener(sType, function() {
fn.call(el, e)
}, capture)
}
} else {
return function(el, sType, fn) {
el.attachEvent('on'+sType, function(e) {
fn.call(el, e)
})
}
}
})
var addEvent = curEvent(); // addEvent 这回获得的,就是if..else...里面的那个return 的function,因此只须要curEvent()执行一遍判断了if..else,其余时候就都不须要判断了
addEvent(elem)
复制代码
2. 函数的bind
咱们总会看到,函数能够这样 test.bind(this),其中bind函数就是柯里化的思想
Funtion.prototype.bind()
var foo = {
x: 888
}
var bar = function(e) {
console.log(this.x, e)
}
Function.prototype.testBind = function(scope) {
var fn = this; // 指向的 bar
return function() {
return fn.apply(scope, [].slice.call(arguments))
}
}
var test = bar.testBind(foo) // 绑定 foo ,延迟执行
console.log(test)
test(2323) // 执行, 结果是 888 2323
复制代码
将传入的第一个参数(foo),看成以后函数的执行上下文,,,其余参数 再传给 调用的方法(函数自己不执行,只进行了bind绑定,之后函数执行的时候,至关于了 延迟执行) , 因此至关于,预先绑定了对象并返回了函数,以后再执行函数,符合柯里化。
3.Redux中的 applyMiddle 中间件原理
let store = applyMiddleware(middleware1,middleware2)(createStore)(rootReducer);
export default function createLogger({ getState }) {
return (next) => // return function
(action) => {
const console = window.console;
const prevState = getState();
const returnValue = next(action);
const nextState = getState();
const actionType = String(action.type);
const message = `action ${actionType}`;
console.log(`%c prev state`, `color: #9E9E9E`, prevState);
console.log(`%c action`, `color: #03A9F4`, action);
console.log(`%c next state`, `color: #4CAF50`, nextState);
return returnValue;
};
}
复制代码
做用总结
最后:如有错误之处,还请见谅,提出后会立刻修改~~~
转载请注明出处,谢谢~~