return a + b + c + d;
}
//通常调用方式
var sum = add(1, 2, 3, 4);
//柯里化的调用方式
var curryAdd = Curry(add);
var sum = curryAdd(1)(2)(3)(4);
//或者很多奇怪的方式调用
var sum = curryAdd(1, 2)(3, 4);
var sum = curryAdd(1, 2, 3)(4);
var sum = curryAdd(1)(2, 3, 4);
//…诸如此类
2.分析
2.1 柯里化简化版本分析
首先我们考虑一种比较简单的情况:两次调用以内必须传递函数所需的所有参数。
//诸如此类调用方式
var curryAdd = Curry(add);
var sum = curryAdd(1,2)(3,4);
var sum = curryAdd(1,2,3)(4);
// …
难点:
-
预存储第一次调用的参数
-
第二次调用时,两次传入的参数合并
因为需要调用两次,因此subCurry需要返回一个函数(思想类似与jq的链式调用)
function subCurry (fn) {
//取出第一次调用时传入的参数
//取出除了fn之外的参数
var args = [].slice.call(arguments, 1);
//第二次调用
return function () {
//参数拼接
//args.concat([].slice.call(arguments,0))
//由于事先规定两次调用参数必须传递达到fn调用需求
//因此直接调用函数fn
return fn.apply(this, args.concat([].slice.call(arguments,0)));
}
}
function add (a, b, c, d) {
return a + b + c + d;
}
var myAdd = subCarry(add, 1 , 2)
console.log(myAdd(3, 4)) //10
2.2 柯里化全面版本
//获取形参个数的方式: 函数名.length
//获取实参个数的方式:arguments.length
function curry (fn, length) {
length = length || fn.length;
//如果实参个数等于满足函数调用的形参个数
//执行函数
return function () {
if (arguments.length >= length) {
return fn.apply(this, arguments);
}else {
//如果实参个数不等于满足函数调用的形参个数
//因此需要再次传递参数,直至达到要求
//那么再一次传递参数,要执行什么样的流程那?
//1. 新传入的参数和已经传入参数进行拼接
// subCurry
//2. 拼接之后再次检查是否达到要求
// curry
//3. 如果达到要求,执行函数
//4. 如果没有达到要求,再次执行1.2.3步骤(递归)
var combined = [fn].concat([].slice.call(arguments, 0));
return curry(subCurry.apply(this, combined), length - arguments.length);
}
总结
大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。