使用Underscore.js,我可以编写以下内容,返回42
:
_([42, 43]).chain()
.first()
.value()
我有自定义功能,而不是名为double()
的Underscore.js的一部分:
function double(value) { return value * 2; };
我希望能够在Underscore链中调用此函数,就像它是Underscore的一部分一样。我想写下面的内容,我想返回84
:
_([42, 43]).chain()
.first()
.double()
.value()
这不起作用,因为Underscore没有定义double()
。我可以使用tap()
,如下所示:
_([42, 43]).chain()
.first()
.tap(double)
.value()
这是有效的,但tap
将函数应用于其参数并返回参数,而不是函数的结果。因此,在我看来,我需要一种tap
来返回应用于其参数的函数的结果。在Underscore.js中有这样的东西吗?我错过了一些非常明显的东西吗?
答案 0 :(得分:24)
找不到返回函数返回值的tap
运行,我定义一个take
并添加到_
:
_.mixin({take: function(obj, interceptor) {
return interceptor(obj);
}});
然后假设我有:
function double(value) { return value * 2; };
我可以写:
_([42, 43]).chain()
.first() // 42
.take(double) // Applies double to 42
.value() // 84
您可以在对象上查看take
map
,而不是列表。想试试这个吗?请参阅此example on jsFiddle。
答案 1 :(得分:5)
所以你有一个自定义功能:
function double(value) { return value * 2; }
您可以使用mixin
扩展Underscore:
_.mixin({ double:double });
现在您可以从Underscore对象_
调用您的函数:
_.double(42); // 84
并从chain
返回的包装对象:
_([42, 43]).chain()
.first()
.double() // double made it onto the wrapped object too
.value(); // 84
答案 2 :(得分:5)
好吧,我刚刚第一次阅读下划线注释源代码。但我认为你可以这样做:
function double(value) { return value * 2; };
var obj = _([42, 43]).addToWrapper({double:double});
obj.chain()
.first()
.double()
.value();
语法/详细信息可能不正确,但核心问题是:当您调用_([42,43])
时,您将下划线作为函数调用。执行此操作时,它会实例化一个新对象,然后将大多数下划线函数混合到该对象中。然后,它将该对象返回给您。然后,您可以将自己的函数添加到该对象,并且这些函数都不会污染“_”命名空间本身。
这就是下划线.js代码对我来说的样子。如果我错了,我想找出答案,希望有人会解释原因。
编辑:我实际上已经大量使用了underscore.js大约一个月了,而且我对它非常熟悉。我现在知道它的行为就像我在这里所说的那样。当您将_作为构造函数调用时,您将获得自己的“命名空间”(只是一个对象),并且您可以使用addToWrapper()向其添加内容,这些内容显示在您的命名空间中但不会显示在“global”“_”中命名空间。所以OP想要的功能已经内置了。(而且我对下划线印象非常深刻,顺便说一下,它的表现非常出色)。答案 3 :(得分:0)
很容易实现这一目标的方法,这就是一个这样的解决方案:
_.chain([42,43])
.first(1)
.map(double)
.first()
.value();
// 84
但是,我建议使用Ramda然后使用自动咖喱和管道/撰写这些类型的任务是微不足道的:
R.pipe(R.head, R.multiply(2))([42, 43]); // 84
equivalent to:
R.compose(R.multiply(2), R.head)([42, 43]); // 84
如果你想扩展解决方案,根据OP的要求,先取两个项目,而不是单个值,那么:
R.pipe(R.take(2), R.map(R.multiply(2)))([42, 43]) // [84, 86]
然而,在Ramda R.compose是优选的。无论哪种方式,对于像这样的琐碎任务,它往往更方便,更容易使用。
答案 4 :(得分:0)
看起来lodash已经实现了您正在寻找的东西:
_.thru(value, interceptor)
来自文档:
此方法与_.tap类似,只是它返回结果 拦截器
答案 5 :(得分:-1)
map
是否适用于此?
_([42, 43]).chain()
.first()
.map(double)
.value()
修改强>
从文档中看来map
只有在调用first
之前放置它才会起作用:
_([42, 43]).chain()
.map(double)
.first()
.value()
答案 6 :(得分:-1)
使用compose
是处理这种情况的另一种方法,但我认为添加take
as I suggested earlier这样的函数是更好的解决方案。不过,以下是使用compose
代码的代码:
function double(value) { return value * 2; };
_.compose(
double,
_.first,
_.bind(_.identity, _, [42, 43])
)();
初始值需要通过返回该值的函数提供(此处通过currying identity
完成),并且函数需要列在另一个函数中,这与您对链的相反对我来说这看起来很不自然。