【问题标题】:Underscore.js _.tap() function what is a method chain?Underscore.js _.tap() 函数什么是方法链?
【发布时间】:2013-12-01 01:41:58
【问题描述】:

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) ->,那么这是否“敲入”了对象字面量的方法链?

【问题讨论】:

    标签: javascript underscore.js chaining method-chaining


    【解决方案1】:

    来自fine manual

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

    因此,在 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, func) { func(x); return x })
    

    但这会让你的意图很明确。实际上,_.tap 让您可以在不更改数据的情况下查看通过方法链的数据。

    【讨论】:

    • 您能澄清一下wrapped object 的意思吗?对象字面量 { obj } ?
    • _.chain(x)_(x).chain()x 包裹在另一个支持下划线功能的对象中。然后每个 Underscore 函数识别它正在处理一个被包装的对象,并为链中的下一步维护包装器..
    【解决方案2】:

    我同意文档中的示例是愚蠢的,因为 alerting 迭代对象绝不是您在真实情况下想要做的事情(除非您正在调试并且想知道对象在 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 );
    

    这个场景真的很适合链接:上面的所有代码本质上都是创建和连续修改一个对象。链接使这一点变得清晰,并阻止你不断地写作业。唯一的问题是我声明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();
    

    【讨论】:

    • 谢谢巴尼,这个答案也有助于我的理解。我首先接受 muistooshort 的回答。
    • 谢谢,帮了大忙
    【解决方案3】:

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

    • _.chain([1,2,3,300]) 将数组包装在下划线包装器中,该包装器具有 filtertapmapvalue 等方法。
    • .tap(alert) 解包来自filter() 的结果,使用解包对象调用alert(),然后再次打包并返回它
    • .value() 返回被包装的对象(减去包装器)。

    【讨论】:

      【解决方案4】:

      正如您所描述的,方法链接将方法相互链接起来。关于_.tap 的关键细节是每个方法的结果都会传递给下一个

      _.tap 允许您插入结果未通过的方法。将上一个方法的结果传递给_tap 之后的方法。这允许在不更改链结果的情况下处理链中的中间结果。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-26
        • 1970-01-01
        • 1970-01-01
        • 2019-06-13
        • 1970-01-01
        • 2010-09-20
        • 2012-05-13
        • 2011-04-26
        相关资源
        最近更新 更多