-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第 84 题:请实现一个 add 函数,满足以下功能。 #134
Comments
之前写过 2 篇文章,可以参考一二。 其中第一篇文章给出了前三个功能的实现,并没有覆盖到后面三种。 |
实现 1: function currying(fn, length) {
length = length || fn.length; // 注释 1
return function (...args) { // 注释 2
return args.length >= length // 注释 3
? fn.apply(this, args) // 注释 4
: currying(fn.bind(this, ...args), length - args.length) // 注释 5
}
} 实现 2: const currying = fn =>
judge = (...args) =>
args.length >= fn.length
? fn(...args)
: (...arg) => judge(...args, ...arg) 其中注释部分
|
const curry = (fn, arity = fn.length, ...args) =>
arity <= args.length ? fn(...args) : curry.bind(void 0, fn, arity, ...args); |
function add() {
let args = [].slice.call(arguments);
let fn = function(){
let fn_args = [].slice.call(arguments)
return add.apply(null,args.concat(fn_args))
}
fn.toString = function(){
return args.reduce((a,b)=>a+b)
}
return fn
} |
function add(){
let args = [...arguments];
let addfun = function(){
args.push(...arguments);
return addfun;
}
addfun.toString = function(){
return args.reduce((a,b)=>{
return a + b;
});
}
return addfun;
} |
还有一种方法 function add(){
if(arguments.length === 0){
let num = 0;
add.args.forEach(v=>{
num += v;
});
add.args = null;
return num;
}else{
add.args = add.args ? add.args : [];
add.args = add.args.concat([...arguments]);
return add;
}
}
add(1)(2)(3)();
add(1, 2)(3)(8)(); |
function curry (fn) {
const finalLen = fn.length
let args = [].slice.call(this,1)
return function currying () {
args = args.concat(Array.from(arguments))
const len = args.length
return len >= fn.length ? fn.apply(this, args) : currying
}
}
function add (a,b,c) {
return a+b+c
}
const add1 = curry(add)
console.log(add1(1, 2)(3)) |
function add(...args) {
let sum = 0;
const innerAdd = (...args) => {
args.forEach(i => (sum += i));
return innerAdd;
};
innerAdd.toString = () => sum;
return innerAdd(...args);
} |
如果要做成高阶函数以便支持任意迭代器,累加器的初始值设定要麻烦一点 写了一个支持以上所有特性的 const curryReducer = (fn) => {
return (...args) => {
let runned = false;
const chain = (...args) => {
if (!args.length) return chain;
chain.acc = (runned ? [chain.acc] : []).concat(args).reduce(fn);
!runned && (runned = true);
return chain;
};
chain.acc = undefined;
chain.toString = () => chain.acc;
return chain(...args);
};
}; // * ---------------- simple add function
const add = curryReducer((a, e) => a + e);
console.log('' + add(1, 2, 3)()(4, 5)(6)(7)(8, 9, 10)); const method = {
add: (a, e) => a + e,
minus: (a, e) => a - e,
times: (a, e) => a * e,
devide: (a, e) => a / e,
};
Object.values(method).forEach((e) => {
console.log('batch test -------------- method is: ', e);
const chainFn = curryReducer(e);
console.log('' + chainFn());
console.log('' + chainFn(6));
console.log('' + chainFn(6, 2));
console.log('' + chainFn(6)(2));
console.log('' + chainFn()(6)(2));
console.log('' + chainFn(6, 2, 3));
console.log('' + chainFn(6, 2)(3));
console.log('' + chainFn(6)(2)(3));
}); |
function add(...a) {
let sum = a.reduce((p, n) => p + n);
function next(...b) {
let _sum = b.reduce((p, n) => p + n);
sum = sum + _sum;
return next;
}
next.toString = function () {
return sum;
};
return next;
} |
|
@wjryours sum 函数定义的参数长度为 3,调用时参数为 4,所以问题出在这里 |
柯里化生成的 add 函数若是存储的形参个数达不到定义的参数长度, 则是返回 [Function] 那么如题 add(1) ==>1 , add(1)(2) ==> 3 则不是没有实现吗 |
我觉得题目出的不好(描述有歧义)。 如果是柯里化,那么缺少参数的时候是等待所有参数到齐则再开始进行运算,并返回计算结果。 至于直接能读到(toString),这是一个 trick。 至于如何实现题目本身 |
const curry = fn => {
const len = fn.length;
return function curried(...args) {
if (args.length === len) {
return fn.apply(null, args);
}
return (..._args) => {
return curried.apply(null, [...args, ..._args]);
};
};
};
const sum = (x, y, z) => x + y + z;
const add = curry(sum);
// 6
add(1, 2, 3);
// 6
add(1,2)(3);
// 6
add(1)(2,3);
// 6
add(1)(2)(3); |
// 第一步,先实现加和运算
var add = function (a, b) {
return a + b;
}
var currying = function (fn, defineVal = 0) {
return function (...args) { // 第一次调用的是这个函数
// 每次执行前先进行和的初始化
var sum = defineVal;
function func(...argts) { // 第二次之后调用的是这个函数
if (args.length === 0) {
return func.toString();
} else {
argts.unshift(sum);
sum = argts.reduce(fn);
return func;
}
}
func.toString = () => sum;
return func(...args);
}
}
var add = currying(add);
console.info(add(1)); // => 1
console.info(add(1)(2)); // => 3
console.info(add(1)(2)(3)); // => 6
console.info(add(1, 2)(3)); // => 6
console.info(add(1)(2, 3)); // => 6
console.info(add(1, 2, 3)); // => 6
console.info(add(1, 2, 3)(4)); // => 10 |
|
`
` |
|
let timer = null
function add(...arg1){
return function(...arg2){
let arg = [...arg1,...arg2]
clearTimeout(timer)
timer = setTimeout(()=>{
console.log(arg.reduce((p,c)=>p+c))
},0)
return add(...arg);
}
}
add(2,3)(4)(5,6)(9)()(1) //30 |
|
诸位真的是大佬---膜拜了 我看了半天算是看懂函数柯里化的应用了function Add(a, b, c) {
return a + b + c;
}
function cuuring(fn) {
let finallen = fn.length;
var args = []
return function digui() {
var innerargs = Array.prototype.slice.call(arguments);
args = args.concat(innerargs);
return args.length >= finallen ? fn.apply(null, args) : digui;
}
}
var add1 = cuuring(Add);
console.log(add1(1)(2)(3)) |
看来半天 不明白 toString 是怎么调用的... |
感觉关键点在重写函数toString方法啊,我就一直在想,怎么又返回函数,而最后又输出结果,真棒! |
function add(...num) {
let res = 0 //第一次调用函数时生成一个闭包来存储结果
num.forEach(item => res += item) //遍历输入参数加到res上
let ret = function (...num) {
num.forEach(item => res += item)
return ret
}
ret.toString = function () {
return res
}
ret.valueOf = function () {
return res
}
return ret
}
console.log(add(1)); // 1
console.log(add(1)(2)); // 2
console.log(add(1)(2)(3)); // 6
console.log(add(1)(2)(3,7)(4,5,6));// 28 使用了一个闭包完成了这个效果 |
你这里输出的结果其实是 |
function add(...firstArgs) { 学到了,fn.toString(); |
在不知道会一直调用多少次的情况下, 不返回一个函数, 怎么能够继续调用呀 |
function add() {
const params = [...arguments]
recur.toString = acc;
return recur()
function acc() {
return params.reduce((acc, item) => {
acc += item;
return acc;
}, 0);
}
function recur() {
params.push(...arguments);
if (params.length >= 3) {
return acc()
} else {
return recur
}
}
}
console.log("debug-", add(1, 2));
console.log("debug-", add(1));
console.log("debug-", add(1, 2)(3));
console.log("debug-", add(1)(2, 3));
console.log("debug-", add(1)(2)(3));
console.log("debug-", add(1, 2, 3)); |
这返回的是函数啊?? |
单纯从题意触发,add调用时候必须有toString之类的触发条件;用外部变量保存每次执行累计的参数列表,执行完toString之后清空即可: // * 柯理化函数
let concatArgs = []
function add(...args) {
concatArgs = concatArgs.concat(args)
return add
}
add.toString = function () {
const res = concatArgs.reduce((pre, cur) => pre + cur, 0)
concatArgs = []
return res
}
console.log(add(1)(2)(3) + "") // 6
console.log(add(1)(2, 3) + "") // 6
console.log(add(1, 2)(3) + "") // 6
console.log(add(1, 2, 3) + "") // 6
console.log(add(1).toString()) // 1
console.log(add(1)(2).toString()) // 3
console.log(add(1)(2)(3).toString()) // 6
console.log(add(1)(2, 3).toString()) // 6
console.log(add(1, 2)(3).toString()) // 6
console.log(add(1, 2, 3).toString()) // 6 |
题目不严谨,有歧义。 在实际项目中如果有这样的需求,或者用 toString 这种 hack 的方式实现。 感谢同事不杀之恩吧。 const money = add(1)(2)
typeof money // function
// 同事:“... wtf ?”
const money = add(1)(2)
if (money < 100) money(3)
// 同事:“???”
const money = add(1)(2)
console.log(money) // f 3
// 此处省略 100+ 行代码...
console.log(money) // money:“猜猜我变没变”
// ...卒 |
修改Number满足吗 |
但是这个好像不能执行add(1,2,3)这种 |
做一个可循环调用 function add (...arg1) {
let t = function (...arg2) {
return add(Array.from(arg1).concat(Array.from(arg2)).reduce((a, b)=> {return a+b}))
}
t.toString = ()=>{
return Array.from(arg1).reduce((a, b)=> {return a+b})
}
return t
} |
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
function add(...args) {
let final = [...args];
setTimeout(() => {
console.log(final.reduce((sum, cur) => sum + cur));
}, 0);
const inner = function (...args) {
final = [...final, ...args];
return inner;
}
return inner;
} |
function add() {
} |
const add=(a,b,c)=>a+b+c
const currying=(fn,length)=>{
length=length||fn.length
return (...args)=>args.length>=length?fn(...args):currying(fn.bind(this,...args),length-args.length)
}
const sum=currying(add)
console.log(sum(1)(2)(3));
console.log(sum(1,2)(3));
console.log(sum(1)(2,3));
console.log(sum(1,2,3)); |
const add=(...args)=>{
const fn=(...params)=>add(...args,...params)
fn.toString=()=>args.reduce((a,b)=>a+b)
return fn
}
console.log(add(1,2)(3).toString()); |
function add(...args) {
let nums = [...args];
function _add(...argsNext) {
if (argsNext.length === 0) {
// 不再有参数传入作为计算结果的信号
return nums.reduce((pre, cur) => {
return pre + cur;
}, 0);
} else {
nums.push(...argsNext);
return _add;
}
}
return _add;
} |
function add(...a){
let sum = (...b) => add(...[...a,...b]); //合并参数
let result = a.reduce((x,y) => x+y); //对所有参数进行累加
sum.toString = () => result; //将结果返回
return sum;
}
console.log(add(1,2,3)(2,2).toString()); //10 |
为什么console的时候不会自动调用 toString方法呢,上面的答案在我的chrome控制台里返回的都是函数 |
可以实现连续不定参数的调用,返回参数和 |
function add () {
let sum
let arg = [].concat(...arguments)
const fn = function () {
arg = arg.concat(...arguments)
sum = arg.reduce((pre, next) => pre + next)
return fn
}
fn.toString = function () {
return sum
}
return fn()
}
console.log('//' + add(1, 2)(3)()(4, 5, 6)) |
function addFn(...args) {
return args.reduce((acc, cur) => acc + cur)
}
function currying(fn) {
let args = []
return function demo(...arg) {
console.log(args);
if (arg) {
args = [...args, ...arg]
return demo
} else {
return fn.apply(this, args)
}
}
}
const add = currying(addFn)
console.log(add(1)(2)(3)());
console.log(add(1)(2,3)); |
|
我也遇到了类似的问题,toString的方案在新版的Chrome(我的版本是98)似乎不起作用,打印出来的是一个函数,需要显式调用才能返回结果 |
function add(a) {
var curSum = a;
function res(b) {
curSum += b
return res
}
res.toString = function () {
return curSum
}
return res
} |
建议把题目描述清楚 |
sum = (...nums)=>{
let res = 0;
sum2 = (...nums2)=>{
res = nums2.reduce((acc,cur)=>acc + cur, res);
console.log(res)
return sum2;
}
return sum2(...nums)
}
// 实现 sum 函数
//sum(1)(2)(3)
//== 6; // true
//sum(1, 2, 3) //== 6; // true
// sum(1); // 1
// sum(1)(2); // 3
// sum(1)(2)(3) // 6
// sum(1)(2, 3) // 6
// sum(1, 2)(3) // 6
// sum(1, 2, 3) // 6 |
如果只是打印结果不返回值的话,用个宏任务 function add() {
let sum = {current: 0}
sum.current = [...arguments].reduce((a, b) => a + b)
setTimeout(() => {
console.log(sum.current)
})
function _add() {
sum.current += [...arguments].reduce((a, b) => a + b)
return _add
}
return _add
}
add(1, 2)(3, 4)(5)
add(1)(2)(3)(4, 5, 6)
add(1, 2, 3) 上面那些toString的都是隐式调用的,结果拼接个字符串,或者非全等比较,就这样 add(1, 2)(3) + ''
add(1, 2)(3) == 6 |
题目有让你们调用toString?个个在这乱抄,就不会运行一下? |
这位同学,不必用这种口气说话 |
|
function add(){ |
// 函数求和
function sumFn(...rest) {
return rest.reduce((a, b) => a + b);
}
// 柯里化函数
var currying = function (func) {
// 保存所有传递的参数
const args = [];
return function result(...rest) {
// 最后一步没有传递参数,如下例子
if(rest.length === 0) {
return func(...args);
} else {
// 中间过程将参数push到args
args.push(...rest);
return result; // 链式调用
}
}
}
// 测试
currying(sumFn)(1)(2)(3)(4)(); // 10
currying(sumFn)(1, 2, 3)(4)(); // 10 |
function curry(fn, acc, initValue) {
let args = [];
fun.toString = function () {
if (args.length === fn.length) {
return fn.apply(this, args);
}
const result = args.reduce(acc, initValue);
args = [];
return result;
};
return fun;
function fun() {
let result = fun;
args = args.concat([...arguments]);
if (args.length === fn.length) {
result = fn.apply(this, args);
args = [];
}
return result;
}
}
var add = curry(
(a, b, c) => {
return a + b + c;
},
(acc, a) => acc + a,
0
);
console.log(add(1).toString()); // 1
console.log(add(1)(2).toString()); // 3
console.log(add(1)(2)(3)); // 6
console.log(add(1)(2, 3)); // 6
console.log(add(1, 2)(3)); // 6
console.log(add(1, 2, 3)); // 6 |
|
The text was updated successfully, but these errors were encountered: