zoukankan      html  css  js  c++  java
  • 浅谈JavaScript中的柯里化函数

      首先,不可避免的要引经据典啦,什么是柯里化函数呢(from baidu):

         在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。

    用于创建已经设置好了一个或多个参数的函数 与函数绑定相似,他们之间的区别在于:当函数被调用时,返回的函数还需要设置一些传入的参数

      
    下面我们来看看具体的代码:
    function curry(fn){
                var args = Array.prototype.slice.call(arguments, 1);
                return function(){
                    var innerArgs = Array.prototype.slice.call(arguments),
                        finalArgs = args.concat(innerArgs);
                    return fn.apply(null, finalArgs);
                };
            }

    相应的调用:

    function add(num1, num2){
                return num1 + num2;
            }
            
            var curriedAdd = curry(add, 5);
            alert(curriedAdd(3));   //8

       那么,下面我们来一步一步的解释上面的curry函数:   首先,不要被其形式参数所迷惑,难不成就只能传一个参数了吗?  当然不是,js是支持可变参数的,我们并不要求其参数形式,最终调用者传过来的所有参数我们都可以通过arguments来访问,OK,我们先来解释第一行:

    var args = Array.prototype.slice.call(arguments, 1);

      要读懂这一句的前提是我们要熟悉call函数的调用,以及Array对象的slice方法的熟悉,此处不再累赘,读者可以自行去查,调用slice(1)将会返回除了第一个元素以外的后面的所有的元素的数组形式。 同时他具备将调用者直接将arguments转换为数组形式的能力,我们此处是用函数的arguments去调用的slice();   官方给arguments的定义是:

    An argument is a value (primitive or object) passed as input to a function.

    arguments 对象并不是一个真正的Array。它类似于数组,但没有数组所特有的属性和方法,除了 length。例如,它没有 pop 方法。不过可以通过slice将其转换成数组:

    此处的结果是: args = [5]     此时args保存了来自外部函数的数组

    那么:接下来,我们将一个匿名函数返回给了调用者,此处形成了一个闭包, 对闭包不是很熟悉的童鞋可以看看我之前写过的一篇文章: http://www.cnblogs.com/Frank-C/p/4964999.html

    将这个匿名函数返回以后呢:下一步我们就开始调用了curriedAdd(3):我们现在讲目光转向这个匿名函数:

    return function(){
                    var innerArgs = Array.prototype.slice.call(arguments),
                        finalArgs = args.concat(innerArgs);
                    return fn.apply(null, finalArgs);
                };

    再次调用slice,注意,读者应该将此时的arguments和之前再匿名函数在外curry函数之内的arguments区分,他们的调用者和调用方式都不一样了哦。   此处,我们把调用方传过来的参数转化为数组,—》》》innerArgs = [3]  然后:我们连接两个数组  

    ---》》》finalArgs = [5,3];

    最后我们直接调用之前传入的函数fn(通过curry函数传入)来时实现最终的add方法,此处没有用call函数,而是用的apply函数,是因为关系到他们两个之间的差别,apply的参数是可以用数组包裹的!!!

       通过上面的几步的简单讲解。我们可以总结:函数的柯里化其实就是在调用一个拥有多个参数的函数之前,提前传入他们的部分参数,后期调用时就只要传余下的部分了!   

  • 相关阅读:
    C#磁吸屏幕窗体类库
    准备
    我写的诗
    How to turn off a laptop keyboard
    How to tell which commit a tag points to in Git?
    Why should I care about lightweight vs. annotated tags?
    How to get rid of “would clobber existing tag”
    Facebook, Google and Twitter threaten to leave Hong Kong over privacy law changes
    The need for legislative reform on secrecy orders
    Can a foreign key be NULL and/or duplicate?
  • 原文地址:https://www.cnblogs.com/Frank-C/p/4970164.html
Copyright © 2011-2022 走看看