3

我最近使用了一个不错的 node.js 库,名为Kue
我想更好地了解发生了什么,所以我开始阅读代码......

我偶然发现了一段代码,我的脑海里出现了“WTF !!?!@$@!$”......
这是代码:

function get(obj) {
  var pending = 0
    , res = {}
    , callback
    , done;

  return function _(arg){
    switch (typeof arg) {
      case 'function':
        callback = arg;
        break;
      case 'string':
        ++pending;
        obj[arg](function(err, val){
          if (done) return;
          if (err) return done = true, callback(err);
          res[arg] = val;
          --pending || callback(null, res);
        });
        break;
    }
    return _;
  };
}

像这样使用的:

exports.stats = function(req, res){
  get(queue)
    ('inactiveCount')
    ('completeCount')
    ('activeCount')
    ('failedCount')
    ('delayedCount')
    ('workTime')
    (function(err, obj){
      if (err) return res.send({ error: err.message });
      res.send(obj);
    });
};

.
.
.

那些函数是函数吗?!
他们是如何认识彼此的?
函数第 7 行的“_”(下划线)是什么?

有人可以帮我了解那边发生了什么吗?:)

4

1 回答 1

7

函数确实可以返回函数。以这个函数为例:

function func(text) {
    alert(text);
    return func;
}

显然,任何调用的返回值func将再次为func,因此您可以像这样使用它:

func("hello")("world");

…你会收到两个警报:第一个是“hello”,然后是“world”。

接下来,有一种叫做命名函数表达式的东西。您之前可能见过匿名函数表达式:

doSomething(thing, function(err) {
    // operation completed or something
});

当然,这对于简单的事情非常有用,但有时您希望函数有一个名称,以便它可以引用自身。正如 Kolink 提到的,如果你只是想递归,有arguments.callee,它指的是当前正在执行的函数,但还有另一种方法:你可以给函数一个只在函数内可见的名称,同时仍然让它是一个函数表达式:

doSomething(thing, function myself(err) {
    //                      ^^^^^^
    // now I can refer to myself as myself!
});

下划线是一个有效的标识符,所以它们基本上只是以一种可能难以理解的方式组合这些技术。

于 2013-04-22T00:13:19.103 回答