在JavaScript中的函数声明上声明.autoCurry()会发生什么?

时间:2014-01-14 00:52:36

标签: javascript

我在"Hey Underscore, You're Doing it Wrong" JavaScript谈话(4:15)中遇到了这种语法。我想知道这意味着什么。

var add = function(x,y){
    return x + y;
}.autoCurry();//What is happening in this line.

3 个答案:

答案 0 :(得分:8)

首先让我们看看咖喱和自动咖啡实际上做了些什么。我已经注释了这两个函数的来源(最初在wu.js库中找到):

  ////
  // Type:
  //
  //   ((a,b, ... c) -> d) -> a -> b -> ... -> c -> d
  //
  // Example:
  //
  //   function add(a, b) { return a + b; }
  //   add2 = curry(add, 2)
  //   add2(3)
  //   // 5
  function curry(fn /* variadic number of args */) {
    var args = Array.prototype.slice.call(arguments, 1);
    function f() { return fn.apply(this, args.concat(toArray(arguments))); }
    return f;
  }

  ////
  // Example:
  //
  //   function add(a, b) { return a + b; }
  //   autoCurry(add);
  //
  //   add(2)(3)                     
  //   // 5
  //
  //   add(2, 3) 
  //   // 5 
  function autoCurry(fn, numArgs) {
    numArgs = numArgs || fn.length;
    function f() {
      if (arguments.length < numArgs)
      {
        return numArgs - arguments.length > 0 ?
        autoCurry(curry.apply(this, [fn].concat(toArray(arguments))),
        numArgs - arguments.length) :
        curry.apply(this, [fn].concat(toArray(arguments)));
      }
      else
      {
        return fn.apply(this, arguments);
      }
    }
    f.toString = function() { return fn.toString(); };
    f.curried = true;
    return f;
  }

换句话说,

autoCurry(add)

接受一个带有两个参数并返回一个数字的函数,并返回一个函数A,它接受一个参数并返回一个函数B.其中B是一个函数,它接受一个参数并返回一个数字:

add(1) -> returns a function add1(), which itself takes a single argument. 

接下来,该演讲的演讲者将做以下事情:

  Function.prototype.autoCurry = function(n) { return autoCurry(this, n); }

这只是将autoCurry方法应用于任何给定的函数(self),以便

var add = function(x,y){
    return x + y;
}.autoCurry();

具有与以下相同的效果:

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

答案 1 :(得分:1)

好吧,我不能告诉你什么,确切autoCurry正在做什么......但我可以告诉你的是:

  1. 他们修改了Function构造函数的原型Function.prototype.autoCurry = function () { };
    您在该页面上创建的每个新功能现在都可以访问此方法作为其属性之一 var myFunc = function () { return true; }; myFunc.autoCurry();

  2. 您可以在JS中愉快地将语句链接在一起。
    var myObj = { run : function () { } }, result = myObj.run();
    相同 var result = { run : function () { } }.run();,只要您不关心myObj之后。

  3. 所以:

    1. 你正在创建一个函数,一旦它被创建,你就在它上面运行一个方法,并且该方法的return语句(链中的最后一个东西)被保存到变量中。
    2. 现在,currying是一种获取函数并将其包装在其他函数中的形式,这允许您仅使用所需的一部分参数来调用它。

      function add_two_numbers = function(x,y){return x + y; }

      Currying将允许你这样做:

      var save_x_for_later = curry(add_two_numbers),
          save_y_and_add   = save_x_for_later(3),
          result = save_y_and_add(5);
      
      result; // 8
      

      至于你的新头衔,答案如下: 你会得到一个错误: .autoCurry()不是该语言的一部分。 它是手工编写的,并作为Function.prototype

      放在Function.prototype.autoCurry = function () { }

      我可以进行currying的实现,但如果你没有做太多的函数式编程,或者“lambda”是一个令人头疼的术语,那么你可以用很多东西来解决问题。

答案 2 :(得分:0)

在JavaScript中,函数实例化表达式:

 function name( arg1, arg2, ... ) { /* code */ }

创建一个函数并导致对函数对象的引用。因此,.autoCurry()是对该对象上的属性的引用,显然它被认为是一个函数。

我怀疑您正在查看的示例还有一些其他代码可以将“autoCurry”添加到Function原型对象中。这样,每个函数对象都可以访问该函数作为“autoCurry”属性。