• javascript里的偏函数——本质函数式编程+闭包,返回函数


    最终效果:

    var greet = function(greeting, name) {
      return greeting + ' ' + name;
    };
    
    var sayHelloTo = _.partial(greet, 'hello');
    sayHelloTo('fred');
    // => 'hello fred'

    来自:http://lodashjs.com/docs/#_partialfunc-partials

    除非你已经使用过其他的函数式编程,不然你可能对下面这两个概念很陌生:“偏函数应用”和“函数柯里化“。

    偏函数应用,英文是partial application,也可以译作“局部应用”、“部分应用”、“偏应用”
    函数柯里化,英文是currying,也可以译作“局部套用”、“加里化”、“卡瑞化”
    

    话虽如此,但是假如你一旦理解了这两个概念,你就完全可以在自己的代码里使用他们。

    Functions

    即使你已经很熟悉JavaScript的function, 知道function可以作为返回值,可以作为参数。
    但是我还是推荐你读一下这个第一部分。如果不需要,也可以跳过,直接看局部应用的章节。

    我们首先看一个非常基础的例子:

    function add(a, b) {
      return a + b;
    }
    
    add(1, 2);    // 3
    add(1, 3);    // 4
    add(1, 10);   // 11
    add(1, 9000); // 9001
    

    尽管上面的例子是非常的简单,但是还是演示出了我们反复调用一个function的场景,并且每次传入的第一个参数都是相同的,在上面的代码里就是数字1

    Functions返回Functions

    我们也可以创建一个叫做makeAdder的function,这个function会返回另一个可以传入参数的function。(像这种可以用来创建其他function或object的function,一般会叫做工厂 - factories)

    返回的函数,如果往里面传入参数调用,可以把传入的参数值和原来设的参数值,返回相加的结果。

    // More general function.
    function add(a, b) {
      return a + b;
    }
    
    add(1, 2);  // 3
    add(10, 3); // 13
    
    // More specific function generator.
    function makeAdder(a) {
      return function(b) {
        return a + b;
      };
    }
    
    // More specific functions.
    var addOne = makeAdder(1);
    addOne(2);  // 3
    addOne(3);  // 4
    
    var addTen = makeAdder(10);
    addTen(2);  // 12
    addTen(3);  // 13
    

    上面的代码之所以可行,是因为JavaScript支持闭包的功能,由于闭包的存在,使得function可以访问到这个function外部的变量,甚至在调用这个function时的作用域的外层。

    除此之外,在JavaScript里面,function是一等公民。正因为如此,function可以接受function作为参数,也可以返回function.

    闭包和函数这个一等公名经常一起配合着工作:使得返回的function可以继续使用传入的参数。

    上面的代码给我们提供了一些方便,我们可以不再使用add(1, 2),而直接使用addOne(2),但是实现这个并不是不需要付出代价的。

    首先,实际做加法的逻辑在上面两个例子的代码中还是重复的,这样还是会有些问题。

    其次,对每个类似于上面的加法场景,用这种方式去独立除不同的逻辑,我们将需要手工创建makeSomething的工厂function。

    Functions接受Functions

    下面的逻辑步骤是创建一个更普遍的工厂function,不仅接受一个要绑定的参数,也会接受一个function,这个function里面包含了所有的核心逻辑。(传入到其他function的function,一般被成为回调函数-callbacks)

    用这种方式,一个单独的工厂function能够被用来创建function绑定。

    注意,原始的function被没有被更新,并且他们的行为也不会改变。他们很容易被调用。

    // Relatively flexible, more specific function generator.
    function bindFirstArg(fn, a) {
      return function(b) {
        return fn(a, b);
      };
    }
    
    // More general functions.
    function add(a, b) {
      return a + b;
    }
    
    add(1, 2);           // 3
    
    function multiply(a, b) {
      return a * b;
    }
    
    multiply(10, 2);     // 20
    
    // More specific functions.
    var addOne = bindFirstArg(add, 1);
    addOne(2);           // 3
    addOne(3);           // 4
    addOne(10);          // 11
    addOne(9000);        // 9001
    
    var multiplyByTen = bindFirstArg(multiply, 10);
    multiplyByTen(2);    // 20
    multiplyByTen(3);    // 30
    multiplyByTen(10);   // 100
    multiplyByTen(9000); // 90000
    

    上面这段代码,亮点不在于它可以将某个参数绑定到任意的function,并且这个参数作为绑定的function的第一个参数,它还能将方法绑定它自己身上作为第一个参数,因此创建了一个可绑定的function

    想想这种情况:假如bindFirstArg能够将第一个参数绑定到一个function,但是这个function可以接受两个参数,比如传进去1和10,1用来加,10用来乘。
    bindFirstArg可以接受两个2参数,假如第一个参数是它自己,也就是bindFirstArg可以用来绑定它自己。

    看下面的例子:

    // More specific function generator.
    var makeAdder = bindFirstArg(bindFirstArg, add);
    
    // More specific functions.
    var addOne = makeAdder(1);
    addOne(2); // 3
    addOne(3); // 4
    
    var addTen = makeAdder(10);
    addTen(2); // 12
    addTen(3); // 13
  • 相关阅读:
    字节流与字符流,字节流和字符流的使用哪个多?
    java 读写操作大文件 BufferedReader和RandomAccessFile
    hibernate官网文档
    阿里云centos怎么用xshell5登陆
    STM8L使用外部8M HSE
    vscode函数注释添加【转载】
    某个通信的异常判断存在于两个任务中时计算通信超时的一种思路
    STM32F0芯片读保护
    FrameworkCubeMX.gpdsc missing的问题
    git忽略已经提交的文件【转载】
  • 原文地址:https://www.cnblogs.com/bonelee/p/6102535.html
Copyright © 2020-2023  润新知