Underscore.js _.tap()函数什么是方法链?

时间:2013-12-01 01:41:58

标签: javascript underscore.js chaining method-chaining

Underscore.js文档解释了_.tap()函数“点击”到方法链中。 http://underscorejs.org/#tap

我无法效仿他们的榜样:

_.chain([1,2,3,200])
  .filter(function(num) { return num % 2 == 0; })
  .tap(alert)
  .map(function(num) { return num * num })
  .value();
=> // [2, 200] (alerted)
=> [4, 40000]

在这种情况下,方法链是什么?我一直认为方法链是链接方法的概念:object.foo().bar().baz()

我见过使用这种方法的例子:module.exports = _.tap {}, (connectors) ->,这也是“点击”对象文字的方法链吗?

4 个答案:

答案 0 :(得分:10)

来自fine manual

  

<强>链接
  [...]
  调用 chain 将导致所有将来的方法调用返回包装对象。完成计算后,使用检索最终值。

因此,在Underscore上下文链接与在其他地方链接相同,除了您在包装对象上链接Underscore方法。首先调用_.chain来获取包装器:

_(obj).chain()

然后你在_.chain返回的内容上调用Underscore方法,它们也将返回包装对象:

_(obj).chain()
      .filter(function(x) { ... })
      .map(function(x) { ... })
      ...

最后你调用_.value打开链接包装器:

var result = _(obj).chain()
                   .filter(function(x) { ... })
                   .map(function(x) { ... })
                   ...
                   .value();

返回_.tap。全部tap does is this

_.tap = function(obj, interceptor) {
  interceptor(obj);
  return obj;
};

所以它调用传递的函数interceptor对迭代的值进行迭代,并返回正在迭代的内容而不对其做任何事情。 _.tap与以下内容相同:

.map(function(x) { f(x); return x })

但它会使你的意图明确。实际上,_.tap允许您在不更改数据的情况下查看通过方法链的数据。

答案 1 :(得分:8)

我同意文档中的示例是愚蠢的,因为alert迭代对象永远不是你想要在真实情况下做的事情(除非你正在调试并希望知道对象的状态2个链式方法 - 但在这种情况下,它可能只是警告[object Object]; console.log更合适但不会按预期工作[但我离题])。以下是非链接工作流程的示例:

var x = { a: 1, b: 2, c: 3 };

x = _.filter( x, function( value ){
  return ( value % 2 === 0 );
} );

x.length = _.size( x );

x = _.pairs( x );

这种情况真的很适合链接:上面的所有代码实际上都是创建并连续修改一个对象。 Chaining清楚地说明了这一点,并阻止你不断写作。唯一的问题是我声明length的行 - 它不能完全适合链,因为它是唯一的声明,它不是简单地在对象上运行下划线方法并将结果分配回该对象。这就是tap的用武之地:你想做一些不容易在链中链接的东西。以下是他对工作流程的看法:

var x = _
  .chain( { a: 1, b: 2, c: 3 } )
  .filter( function( value ){
    return ( value % 2 === 0 );
  } )
  .tap( function( x ){
    x.length = _.size( x );
  } )
  .pairs()
  .value();

答案 2 :(得分:1)

如您所述,方法链接将方法链接在一起。关于_.tap的关键细节是将每种方法的结果传递给下一个

_。tap可让您插入结果未通过的方法。将先前方法的结果传递给_tap之后的方法。这允许在链中处理中间结果而不改变链的结果。

在你的例子中,如果单独调用alert会破坏链,因为它不会返回任何内容。使用_.tap会导致上一个方法(filter(function(num) { return num % 2 == 0; }))的结果传递给以下方法(map(function(num) { return num * num })

答案 3 :(得分:1)

示例中的链是filter().tap().map()

  • _.chain([1,2,3,300])在包含filtertapmapvalue等方法的下划线包装中包装数组。
  • .tap(alert)展开filter()的结果,使用展开的对象调用alert(),然后将其再次包装并将其返回
  • .value()返回包装对象(减去包装器)。