scope calling functions inside functions

后端 未结 5 1595
既然无缘
既然无缘 2021-02-04 01:23

Hope somebody finds the time to explain little about functions in functions and scoping. I am trying to understand little more on functions and scope of variables and found a qu

5条回答
  •  情话喂你
    2021-02-04 01:34

    If you take this code and simplify it to the bare minimum I would be easier to understand. Take a function add that sums only 2 numbers:

    function add(x,y) {
      return x + y;
    }
    

    The above is a "normal" function. If you don't pass all the arguments you'll get unexpected results.

    Now, if you want a function that adds 2 to any number, you could partially apply an argument to add, for example:

    function add2(x) {
      return add(2, x);
    }
    

    But in JavaScript we have first class functions (objects that can be passed around), so a function can take functions as inputs and return other functions. This is where "currying" comes in handy. While "partial application" lets you fix function arguments, "currying" takes a function of many arguments and breaks it down into a function of a single argument that returns another function of one single argument until all the arguments have been evaluated, in order, and then returns the result. For example:

    function add(x) {
      return function(y) {
        return x + y;
      }
    }
    

    Now you can create a function add2 by currying the function add:

    var add2 = add(2);
    add2(1); //=> 3
    

    The normal function and the curried one have equivalent computations where:

    add(1, 2) === add(1)(2)
    

    This is what makes "several parentheses" possible.

    In JavaScript "scope" and "closure" refer to functions but they're different concepts. A "scope" determines the reach/privacy of your variables while a "closure" lets you encapsulate code and carry it around. In the curried function above the variable x is kept in memory through closure because it's referenced inside the returned function object.

    A particular limitation of "currying" is that you can't have functions of dynamic arity; the number of arguments must be fixed. This is not the case in the code you post where your sum function must be able to add a new number to the previous sum indefinitely.

    Similarly to "currying" there's the idea of "generators"; a pattern to model sequences of lazy computation, in this case just adding a number to the previous sum on demand.

    function sum(a) { // begin closure
      var sum = a; // kept in memory...
      function f(b) {
        sum += b; //...because you use it here
        return f;
      }
      f.toString = function() { return sum };
      return f;
    } // end closure
    

    A different (maybe more clear) way to express your code would be to return an object to chain the computations, where you can either add a new number to the previous sum, or get the total sum so far:

    function add(a) {
      var sum = a;
      return {
        plus: function(b) {
          sum += b;
          return this;
        },
        sum: function() {
          return sum;
        }
      }
    }
    
    add(1).plus(2).plus(3).sum(); //=> 6
    

    In your code the returned function f acts as plus and toString as sum which retrieves the value.

提交回复
热议问题