【Vue源码】函数柯里化
概念:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数;
先看一个简单例子,add
函数接受 2 个参数(或者多个),addX
函数接受 1 个参数。换而言之,所谓"柯里化",就是把一个多参数的函数,转化为单参数函数。将一个函数转换为一个新的函数:
// 非柯里化 function add(x, y) { return x + y; } add(1, 2) === 3; // true // 柯里化 function addX(y) { return function(x) { return x + y; }; } addX(2)(1) == 3; // true
如何实现柯里化函数 curry
在下面的例子中我们对 add 进行了柯里化,从结果上可以看到当参数为 1 个时返回的是个函数,当参数为 2 个的时候返回函数,当参数为 3 个的时候返回函数执行结果
。
var _ = require("ramda"); var add = function(a, b, c) { return a, b, c; }; var curry_add = _.curry(add); console.log(curry_add(1)); // 输出函数 console.log(curry_add(1)(2)); // 输出函数 console.log(curry_add(1)(2)(3)); // 输出结果
根据上述的小栗子,可以得到,柯里化后的函数
如果接受到全部参数则返回函数执行结果
,否则返回一个柯里化函数
。
很容易想到以下伪代码
var curry = function(fn) { return function() { // 假设柯里化的函数叫 curry_fn // if "curry_fn接受到的参数数量等于fn接受参数的数量" // return "fn的执行结果" // else return "一个柯里化函数" }; };
上述伪代码是不是很像递归?
- 递归出口:curry_fn接受到的参数数量等于fn接受参数的数量
- 重复逻辑:return "一个柯里化函数"
于是有了以下简单实现柯里化的代码
var curry = function(fn) { var limit = fn.length; // fn接受的参数个数 var params = []; // 存储递归过程的所有参数,用于递归出口计算值 return function _curry(...args) { params = params.concat(args); // 收集递归参数 if (limit <= params.length) { // 返回函数执行结果 return fn.apply(null, params); } else { // 返回一个柯里化函数 return _curry; } }; };