不找工作!
最近看到一个挺有意思的题,如下:
// 编写一个 add 函数,要求如下均打印 6
console.log(add(1,2,3)) // 打印6
console.log(add(1)(2,3)) // 打印6
console.log(add(1)(3)(2)) // 打印6
console.log(add(1,2)(3)) // 打印6
回到学生时代,遇到问题,那首选需要分析题目,该题存在如下一些点:
- 链式调用
- 闭包
首选分析一下链式调用,add()()
需要函数的返回值是一个函数,那么会存在如下结构:
const add = () => {
return () => {}
}
但题目明显没这么简单,因为这里是多层调用 add()()()
,所以需要循环返回,改造如下:
const add = () => {
const fn = () => {
console.log('fn')
return fn;
}
return fn;
}
当我们执行 add()()()
时会打印2次 fn 并得到一个 fn
函数, 这样看上去满足了链式调用的需求,但如何将值给返回呢?
由于需要返回累加值,所以我们需要用到闭包的知识,魔改一下:
function add(){
const args = [...arguments];
function fn(){
args.push(...arguments);
console.log(args); // [1,2,3]
return fn;
}
return fn;
};
add(1,2)(3); // fn
细心的你也许会问,这里为什么不用 es6 的箭头函数了,原因是我们需要使用 arguments
,箭头函数没有 arguments
吗? 不是没有,是没有自己的 arguments
,这涉及到作用域了,有兴趣的可以咨询查阅,不展开。
可以看出,我们已经将所有的形参保存 args 里面了,并返回了 fn,如何从 fn 上获取 args 的累加值?
这其实是这道题的难点,高考可以放到第 21 题了。
先简单介绍下 valueOf,其会返回指定对象的原始值。
'1'.valueOf(); // '1'
(1).valueOf(); // 1
[1,2].valueOf(); // [1,2]
const obj = {name: '柯南'};
obj.valueOf() === obj; // true
valueOf 除了可以返回原始值之外,我们还可以对其进行修改
const obj = {name: '柯南'};
obj.valueOf = () => '小明';
obj.valueOf(); // '小明'
因此,我们只需要修改 fn 的 valueOf 即可得到 reduce 值
function add(){
const args = [...arguments];
function fn(){
args.push(...arguments);
return fn;
}
fn.valueOf = () => args.reduce((a,b) => a + b, 0);
return fn;
};
console.log(add(1,2,3).valueOf()); // 6
console.log(add(1,2)(3).valueOf()); // 6
满足要求了吗?好像并没有,求大哥指点。