javascript Underscore.js:如何链接自定义函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3945673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Underscore.js: how to chain custom functions
提问by avernet
Using Underscore.js, I can write the following which returns 42:
使用Underscore.js,我可以编写以下返回42:
_([42, 43]).chain()
.first()
.value()
I have custom function, not part of Underscore.js called double():
我有自定义函数,而不是 Underscore.js 的一部分,称为double():
function double(value) { return value * 2; };
I would like to be able to call this function in an Underscore chain, as if it was part of Underscore. I would like to write the following, which I'd like to return 84:
我希望能够在 Underscore 链中调用这个函数,就好像它是 Underscore 的一部分一样。我想写以下内容,我想返回84:
_([42, 43]).chain()
.first()
.double()
.value()
This can't work since Underscore doesn't define double(). I could use tap()as in:
这是行不通的,因为 Underscore 没有定义double(). 我可以使用tap():
_([42, 43]).chain()
.first()
.tap(double)
.value()
This is valid, but tapapplies the function to its argument and returns the argument, not the result of the function. So it looks to me like I would need a sort of tapthat returns the result of the function applied to its argument. Is there anything like this in Underscore.js? Am I missing something terribly obvious?
这是有效的,但tap将函数应用于其参数并返回参数,而不是函数的结果。所以在我看来,我需要一种tap返回应用于其参数的函数的结果。Underscore.js 中有这样的东西吗?我错过了一些非常明显的东西吗?
回答by avernet
Not finding a tapthat returns the value returns by the function is runs, I define one which I can takeand add to _:
没有找到tap返回由函数返回的值的运行,我定义了一个我可以take添加到的_:
_.mixin({take: function(obj, interceptor) {
return interceptor(obj);
}});
Then assuming I have:
然后假设我有:
function double(value) { return value * 2; };
I can write:
我可以写:
_([42, 43]).chain()
.first() // 42
.take(double) // Applies double to 42
.value() // 84
You can look at takeas mapon objects, instead of lists. Want to experiment with this? See this example on jsFiddle.
你可以看一下take作为map在对象上,而不是名单。想尝试这个吗?在 jsFiddle 上查看此示例。
回答by Roatin Marth
So you have a custom function:
所以你有一个自定义函数:
function double(value) { return value * 2; }
You can use mixinto extend Underscore with it:
您可以使用它mixin来扩展 Underscore:
_.mixin({ double:double });
Now you can call your function from the Underscore object _:
现在您可以从 Underscore 对象调用您的函数_:
_.double(42); // 84
and from the wrapped object returned from chain:
并从从以下位置返回的包装对象chain:
_([42, 43]).chain()
.first()
.double() // double made it onto the wrapped object too
.value(); // 84
回答by Charlie Flowers
Alright, I'm fresh off of reading the underscore annotated source code for the first time. But I think you can do something like this:
好吧,我是第一次阅读下划线注释的源代码。但我认为你可以这样做:
function double(value) { return value * 2; };
var obj = _([42, 43]).addToWrapper({double:double});
obj.chain()
.first()
.double()
.value();
The syntax/details might not be right, but the core point is this: when you call _([42,43]), you're calling underscore as a function. When you do so, it instantiates a new object and then mixes into that object most of the underscore functions. Then, it returns that object to you. You can then add your own functions to that object, and none of this pollutes the "_" namespace itself.
语法/细节可能不正确,但核心点是:当您调用 时_([42,43]),您将下划线作为函数调用。当您这样做时,它会实例化一个新对象,然后将大部分下划线函数混合到该对象中。然后,它将该对象返回给您。然后您可以向该对象添加您自己的函数,并且这些都不会污染“_”命名空间本身。
That's what the underscore.js code looked like to me. If I'm wrong, I'd like to find out and hopefully someone will explain why.
这就是 underscore.js 代码在我看来的样子。如果我错了,我想找出答案,希望有人能解释原因。
EDIT: I've actually been using underscore.js heavily for about a month now, and I have gotten pretty familiar with it. I now knowit behaves like I said here. When you call _ as a Constructor function, you get back your own "namespace" (just an object), and you can add things to it with addToWrapper() that show up in your namespace but not in the "global" "_" namespace. So the feature the OP wanted is already built in. (And I have been really impressed with underscore, btw, it is very very nicely done).
编辑:我实际上已经大量使用 underscore.js 大约一个月了,我已经非常熟悉它了。我现在知道它的行为就像我在这里说的那样。当您将 _ 作为构造函数调用时,您将获得自己的“命名空间”(只是一个对象),并且您可以使用 addToWrapper() 向其中添加显示在命名空间中但不在“全局”“_”中的内容命名空间。所以 OP 想要的功能已经内置了。(我对下划线印象深刻,顺便说一句,它做得非常好)。
回答by arcseldon
Many ways to easily achieve this, here is one such solution:
有很多方法可以轻松实现这一点,这里是一个这样的解决方案:
_.chain([42,43])
.first(1)
.map(double)
.first()
.value();
// 84
However, I would recommend using Ramdathen with auto-curry and pipe / compose these kinds of tasks are trivial:
但是,我会建议使用Ramda然后使用 auto-curry 和 pipe/compose 这些类型的任务是微不足道的:
R.pipe(R.head, R.multiply(2))([42, 43]); // 84
equivalent to:
R.compose(R.multiply(2), R.head)([42, 43]); // 84
If you wanted to extend the solution to take say the first 2 items, instead of a single value, as requested by the OP, then:
如果您想根据 OP 的要求扩展解决方案以采用前 2 个项目,而不是单个值,则:
R.pipe(R.take(2), R.map(R.multiply(2)))([42, 43]) // [84, 86]
However, in Ramda R.compose is preferred. Either way, for trivial tasks like this, it does tend to be more convenient and easy to use.
但是,在 Ramda R.compose 中是首选。无论哪种方式,对于像这样的琐碎任务,它确实往往更方便和易于使用。
回答by Zaptree
Looks like lodash has implemented exactly what you are looking for:
看起来 lodash 已经实现了你正在寻找的东西:
_.thru(value, interceptor)
from the docs:
从文档:
This method is like _.tap except that it returns the result of interceptor
这个方法类似于_.tap,只是它返回拦截器的结果
回答by Gabe Moothart
Does mapwork for this?
map对这个有用吗?
_([42, 43]).chain()
.first()
.map(double)
.value()
edit
编辑
from the documentation, it looks like mapwould only work if you place it before the call to first:
从文档中,它看起来map只有在您将其放置在调用之前才有效first:
_([42, 43]).chain()
.map(double)
.first()
.value()
回答by avernet
Using composeis another way dealing with the situation, but I think adding a function such as takeas I suggested earlieris a better solution. Still, here is how the code would look like with compose:
使用compose是另一种处理这种情况的方法,但我认为添加一个take我之前建议的函数是一个更好的解决方案。不过,代码如下所示compose:
function double(value) { return value * 2; };
_.compose(
double,
_.first,
_.bind(_.identity, _, [42, 43])
)();
The initial value needs to be provided through a function which returns that value (here done by currying identity), and the functions need to be listed in an other which is the reverse of what you have with a chain, which appears as pretty unnatural to me.
初始值需要通过一个返回该值的函数提供(这里是通过 currying 完成的identity),并且这些函数需要列在另一个中,这与你拥有的链相反,这对我来说看起来很不自然.

