柯里化这个概念确实晦涩难懂,没有深入思考过的人其实真的很难明白这是一个什么东西。看起来简单、简单到或许只需要一行代码:
const curry = fn => (…args) => fn.bind(null, …args);
是的,就是这么简单。
如果单纯的去理解这一句代码,实在太痛苦了,不妨拆开来,一点一点的去看,也不妨再笨点,先尝试着写成传统的ES5,我们用arguments 去代替 ...args 慢慢理解。貌似是下面这样
const curry = function(fn){ return function (){ // 1 return fn.bind(null, arguments) //2 } }
可是看着感觉有点不对劲呢?
显然2处的arguments已经和上面的args已经不是一个东西了,这里的arguments是1处函数调用时的参数,所以要改进下
const curry = function(fn){ let args = [].slice.call(arguments, 1) // 这句话的意思是差不多等于 let args = arguments.slice(1) ,但是argumets不是数组(伪数组),所以不能这么写 return function (){ // 1
let _args = args.concat([].slice.call(arguments)) // 拼接出新的arguments
return fn.bind(null,_args) //2
}
}
这下好像和我们之前看的差不多了嘛,但是这他妈拆了半天函数啥也没说,不是等于放屁吗?
好吧,如果直接去看概念搞不懂的话,换个思路,看代码,如果看懂了,再去想概念不就更加容易理解了吗?
接着再看
fn.bind(null, _args)
这句话是干啥子的,
bind() 方法会创建一个新函数,当这个新函数被调用时,它的 this 值是传递给 bind() 的第一个参数, 它的参数是 bind() 的其他参数和其原本的参数。
懂了吗?
function a(){ return [].slice.call( arguments) } a(1,2,3) // [1,2,3] var _a = a.bind(null, 4,5) _a(1,2,3) // [4,5,1,2,3]
其实只是拼接了参数而已,而且bind返回的是一个函数,等着被调用,
这样看来每次调用curry函数都只是把之前的参数和这次的参数收集到一个数组里,然后返回一个新的函数,而且这个函数已经默认带了之前传入的所有参数。是的,柯里化就是一个参数收集器,返回新的函数而已。
这玩意有啥用?
很多文章都已经说明了,大家可以去参考一下别的文章就可以了。
希望能对大家理解柯里化有些帮助。
参考链接:
http://www.webhek.com/post/javascript-bind.html
https://www.zhangxinxu.com/wordpress/2013/02/js-currying/