在面试题中,学习currying函数
编写一个ADD函数满足如下需求:
add(1); //1
add(1)(2); //3
add(1)(2)(3); //6
add(1)(2, 3); //6
add(1, 2)(3); //6
add(1, 2, 3); //6
此题答案如下,代码为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>面试题7-JS高阶技巧-currying函数</title>
</head>
<body>
<!--
面试题7、编写一个ADD函数满足如下需求
add(1); //1
add(1)(2); //3
add(1)(2)(3); //6
add(1)(2, 3); //6
add(1, 2)(3); //6
add(1, 2, 3); //6
-->
<script>
//方案一:
// function add(...outerArgs) {
// add = function (...innerArgs) {
// outerArgs.push(...innerArgs);
// return add;
// };
// add.toString = function () {
// return outerArgs.reduce((x, y) => x + y);
// };
// return add;
// }
// let res = add(1, 2)(3)(4)(5)(6, 7);
// alert(res); //=>alert会输出的值转换为字符串,使用的(toString())
/*
执行思路:
第一次执行ADD outerArgs=[1,2],并重写ADD,返回ADD,下次执行调用的是重写的ADD函数
第二次执行ADD innerArgs=[3] outerArgs=[1,2,3]
第三次执行ADD innerArgs=[4] outerArgs=[1,2,3,4]
......
outerArgs=[1,2,3,4,5,6,7];
res = add,还是add函数想要的实参的和
*/
// console.log(res.toString());
//方案二-currying()函数混装
function currying(anonymous, length) {
return function add(...args) {//可以理解为代理,与柯理化函数类似
if (args.length >= length) {
// 若参数的个数与length相等,直接传args参数执行求和函数
return anonymous(...args);
}
return currying(anonymous.bind(null, ...args), length - args.length);
}
}
let add = currying(function anonymous(...args) { //传多少值,将多少值得和返回
return args.reduce((x, y) => x + y);
}, 4); //4指最终会有多少个数相加
/*
AO(currying)
anonymous=求和函数
length=4
ADD第一次执行 args=[1,2]
currying第二次执行,currying执行返回新的add
anonymous=求和函数 预先传递的参数[1,2]
length=2
ADD 第二次执行 args=[3]
Currying第三次执行
anonymous=求和函数,预先传递的参数[3]
length=1
ADD函数第三次执行 args=[4]
把上一次的求和函数执行[4]
每一次执行会生成一个不销毁的闭包
*/
console.log(add(1, 2)(3)(4));
</script>
</body>
</html>