函数 add 可以实现连续的加法运算
函数 add 语法如下 add(num1)(num2)(num3)...;
//注意这里是省略号哟,可无限
使用举例如下:
add(10)(10); // 20
add(10)(20)(50); // 80
add(10)(20)(50)(100); // 180
var add30 = add(10)(20); // 30
var add100 = add30(30)(40); // 100
var add31 = add30(1); // 31
var add40 = add31(9); // 40
PHP中文网2017-04-10 15:30:14
@bf 老师的答案非常棒,学习了。不过我想@bf 老师实际上还是搞反了 currying 和 uncurrying。
currying 是将参数提前保存以在下一次调用时不必提供此参数,@bf 老师的代码所做的正是这个工作。而 uncurrying 则是将原来设定好的参数腾出来,使之可以被函数调用者重新设定。在 JavaScript 中常用于将 obj.func(x, y, z, ...)转变为 func(org, x, y, z)。这样做的好处是可以方便地应用 Duck Type
这种特性。@bf 老师后面提供的 curry 代码其实才是真正的 uncurry。(@bf 菜菜已經將自己的答案 reverse 到 r4,which fits the en wikipedia)
另,
如下代码也可以很好的工作(其实还是一种 currying,将每次的和绑定到下次调用,这样就可以连加了):
function add(x) {
function helper(y, x) {
var sum = y + x;
var f = helper.bind(null, sum);
f.toString = function () {
return '' + sum;
};
f.valueOf = function () {
return sum;
};
return f;
}
return helper(x, 0);
}
console.log(+add(10)(10)); // 20
console.log(+add(10)(20)(50)); // 80
console.log(+add(10)(20)(50)(100)); // 180
var add30 = add(10)(20); // 30
var add100 = add30(30)(40); // 100
var add31 = add30(1); // 31
var add40 = add31(9); // 40
console.log(+add30, +add100, +add31, +add40);
实际上就是要把每一次函数调用的结果都区分开而已。
迷茫2017-04-10 15:30:14
javascript
function add(a){ function x(b){ a+=b; return x; } x.toString=function(){return a;} return x; } console.log( add(10)(10) == 20 && add(10)(20)(50) == 80 && add(10)(20)(50)(100) == 180 );// true
返回一个返回自身的函数,就可以做到无限调用。
黄舟2017-04-10 15:30:14
reversed to r4; nonsense was deleted.
這道題考得是柯里化。
function curry(fn) {
return function(x) {
return function g(x, y) {
if (y === void 0)
return x;
else
return g.bind(this, fn(x, y));
}.bind(this, x);
};
}
function add(x, y) {
return x + y;
}
var curried_add = curry(add);
curried_add(1)(2)(); // 3
curried_add(1)(2)(3)(); // 6
curried_add(1)(2)(3)(); // 6
curried_add(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)(15)(16)(17)(18)(19)(20)(); // 210
var a1 = curried_add(1);
var a2 = a1(2);
var a3 = a1(3);
var a4 = a3(4);
a1(), a2(), a3(), a4(); // 1 3 4 8
阿神2017-04-10 15:30:14
这个问题叫做柯里化(curry),不是勇士的库里。柯里化就是预先将函数的某些参数传入,得到一个简单的函数,但是预先传入的参数被保存在闭包中。
具体可以看看这个实现curry
高洛峰2017-04-10 15:30:14
var add = function () {
var args = [].slice.call(arguments),
count = 0;
args.forEach(function (value) {
count += value;
});
return function () {
var args = [].slice.call(arguments);
if (!args.length) {return count;}
args.unshift(count);
return add.apply(null, args);
};
};
还可以这样调用:
var add30 = add(10, 10, 10);
也可以这样调用:
var add30 = add(10)(10)(10);
var add100 = add30(20)(20)(30);
add100(); //100
PHP中文网2017-04-10 15:30:14
我没记错的话这个是这题吧,原题应该是 CodeWar 上的。
js
function add(n) { var temp = n; var func = function(n) { temp += n; return func; }; func.toString = func.valueOf = function() { return temp; }; return func; }
大家讲道理2017-04-10 15:30:14
首先,完全按照题目实现,根本实现不了,add(1)(2)如果返回3,add(1)(2)(3)必然报错。
我们退一步,实现add(1)(2)()返回3,add(1)(2)(3)()返回6。
有两种方法,第一种是每次调用都计算出中间结果,最后无参数调用时把结果返回,另一种是把加数都记下来,无参数调用时执行加法并返回。
第一种:
function add(a) {
if (typeof a === 'undefined') {
return 0;
}
function add_(a, b) {
var s = a + b;
return function (c) {
if (typeof c === 'undefined') {
return s;
}
return add_(s, c);
}
}
return add_(0, a);
}
console.log(add());
console.log(add(1)(2)());
console.log(add(1)(2)(3)());
第二种:
function add(a) {
if (typeof a === 'undefined') {
return 0;
}
if (typeof a !== 'number') {
var sum = 0;
for (var i = 0; i < a.length; ++i) {
sum += a[i];
}
return sum;
}
var args = Array.prototype.slice.call(arguments, 0);
return function (b) {
if (typeof b === 'undefined') {
return add(args);
}
args.push(b);
return add.apply(this, args);
}
}
console.log(add());
console.log(add(1)(2)());
console.log(add(1)(2)(3)());
巴扎黑2017-04-10 15:30:14
php
function add(x){ var sum=x; var tmp=function(y){ sum+=y; return tmp; }; tmp.toString=function(){ return sum; }; return tmp; } console.log(add(1)(2)(3));//6 console.log(add(1)(2)(3)(4)(5));//15
巴扎黑2017-04-10 15:30:14
问他想考你什么
如果想考闭包,和函数式,和原型继承那就写给他,如果他不说
那么直接写个window.sum=0和function add()气死他
1.首先需要优雅点的写法,不写成window.var,所以写个闭包
function foo(){
var bar=function(){}
}
2.然后思考一下函数式累加怎么写,第一步当然是 sum=0+input;
function foo(x){
x=0+x;
var bar=function(){};
}
3.这时,得把x扔进子作用域bar才行,不然就记不住这个sum了.然后进一步的累加就交由bar来处理了,理由同上.
function foo(x){
x=0+x;
var bar=function(y){
x=x+y;
};
}
4.再把整个结构贯通一下,先运行foo,获得result,交由bar,并且return出bar,return bar后才能继续走下一步
//我发现这里好像是markdown??
function foo(x){
x=0+x;
var bar=function(y){
x=x+y;
};
return bar;
}
5.好了,现在到bar了,这就比较简单了,不用考虑闭包这无聊的事,sum_new=sum_odd + input;接着呢 还要继续累加那么,直接无限调用自身就好了,所以bar:return bar;
function foo(x){
x=0+x;
var bar=function(y){
x=x+y;
return bar;
};
return bar;
}
6.其实已经完事了,只不过为了应付原型继承这个考点,还要蛋疼的多写一步.这个也是很赖皮的..我就不想写了,反正上面代码都有了.所以我show我喜欢的写法
function foo(x){
x=0+x;
var bar=function(y){
x=x+y;
return bar;
};
bar.show=function(){console.log(x);}
return bar;
}
result :foo(1)(2)(3).show() = 6
大家讲道理2017-04-10 15:30:14
function add(num) {
var sum = 0;
function cache(arg) {
if (arg === undefined) {
return sum;
} else {
sum += arg;
}
return cache
}
return cache(num);
}
console.log(add(1)(2)());
console.log(add(1)(2)(4)(5)());
唯一的缺点,最后结束时必须再次调用一次。
哪位大神来完善下