The 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) ->
,因此是否可以“点击”到对象文字的方法链中?
连锁[...]调用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
因此它调用传递的函数,对要迭代的值进行_.tap = function(obj, interceptor) {
interceptor(obj);
return obj;
};
并返回要迭代的内容,而不对其进行任何操作。 interceptor
与:
_.tap
但是它使您的意图清晰。实际上,.map(function(x, func) { func(x); return x })
使您可以浏览通过方法链传递的数据,而无需更改该数据。
我同意文档中的示例很愚蠢,因为_.tap
绝不希望在实际情况下执行迭代对象(除非您正在调试并且想知道2个链接方法之间的对象状态—但在这种情况下,它可能只会警告alert
; [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();
:
filter().tap().map()
在下划线包装器中包装一个数组,该包装器具有_.chain([1,2,3,300])
,filter
,tap
,map
等方法value
解开.tap(alert)
的结果,用解开的对象调用filter()
,然后再次将其包装并返回]alert()
返回包装的对象(减去包装)。正如您所描述的,方法链接将方法彼此链接在一起。关于.value()
的关键细节是每种方法的结果都传递给下一个]。
__ tap可让您插入一个方法,其结果未通过
。先前方法的结果将传递到_.tap
之后的方法。这允许处理链中的中间结果,而无需更改链的结果。在您的示例中,如果_tap
单独调用,它将破坏链,因为它不会返回任何内容。使用alert
,可使先前方法(_.tap
)的结果传递到后续方法(filter(function(num) { return num % 2 == 0; })
)