currying - Javascript 连续调用单参函数实现任意参函数
天蓬老师
天蓬老师 2017-04-10 15:28:14
0
14
1447

函数 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
天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全員に返信(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);

实际上就是要把每一次函数调用的结果都区分开而已。

いいねを押す +0
迷茫
javascriptfunction 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

返回一个返回自身的函数,就可以做到无限调用。

いいねを押す +0
黄舟

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
いいねを押す +0
阿神

这个问题叫做柯里化(curry),不是勇士的库里。柯里化就是预先将函数的某些参数传入,得到一个简单的函数,但是预先传入的参数被保存在闭包中。

具体可以看看这个实现curry

いいねを押す +0
小葫芦
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
いいねを押す +0
Ty80

我没记错的话这个是这题吧,原题应该是 CodeWar 上的。

jsfunction add(n) {
    var temp = n;
    var func = function(n) {
        temp += n;
        return func;
    };

    func.toString = func.valueOf = function() {
        return temp;
    };

    return func;
}
いいねを押す +0
大家讲道理

首先,完全按照题目实现,根本实现不了,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)());
いいねを押す +0
巴扎黑
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
いいねを押す +0
巴扎黑

问他想考你什么
如果想考闭包,和函数式,和原型继承那就写给他,如果他不说
那么直接写个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

いいねを押す +0
大家讲道理
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)());

唯一的缺点,最后结束时必须再次调用一次。
哪位大神来完善下

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!