Подчеркивание.js:как связать пользовательские функции
-
08-10-2019 - |
Вопрос
С использованием Underscore.js, я могу написать следующее, которое возвращает 42
:
_([42, 43]).chain()
.first()
.value()
У меня есть пользовательская функция, а не часть Underscore.js, называемая double()
:
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?Я упускаю что-то ужасно очевидное?
Решение
Не найти А. 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
на объектах вместо списков. Хотите поэкспериментировать с этим? Видеть это Пример на jsfiddle..
Другие советы
Таким образом, у вас есть пользовательская функция:
function double(value) { return value * 2; }
Вы можете использовать mixin
продлить подчеркивание с этим:
_.mixin({ double:double });
Теперь вы можете вызвать вашу функцию из объекта подчеркивания _
:
_.double(42); // 84
и от обернутого объекта, возвращаемого из chain
:
_([42, 43]).chain()
.first()
.double() // double made it onto the wrapped object too
.value(); // 84
Хорошо, я впервые в первую очередь читал подчеркивание аннотированного исходного кода. Но я думаю, что вы можете сделать что-то вроде этого:
function double(value) { return value * 2; };
var obj = _([42, 43]).addToWrapper({double:double});
obj.chain()
.first()
.double()
.value();
Синтаксис / детали могут быть не правы, но основная точка в том, когда вы звоните _([42,43])
, Вы называете подчеркивание как функцию. Когда вы этого делаете, он создает новое объект, а затем смешивается в этот объект большинство функций подчеркивания. Затем он возвращает этот объект к вам. Затем вы можете добавить свои собственные функции на этот объект, и ни один из этого не загрязняет сам пространство имен «_».
Это то, как выглядел код underscore.js для меня. Если я ошибаюсь, я хотел бы узнать и, надеюсь, кто-то объяснит, почему.
Редактировать: Я фактически использую подчеркивание. я сейчас знать Это ведет себя так, как я сказал здесь. Когда вы звоните _ в качестве функции конструктора, вы верните свое собственное «пространство имен» (просто объект), и вы можете добавить вещи к нему с помощью AddToWrapper (), которые отображаются в вашем пространстве имен, но не в «глобальном» «_» пространство имен. Таким образом, функция ОП «Требуется» уже встроена. (И я был действительно впечатлен подчеркиванием, кстати, это очень хорошо сделано).
Многие способы легко достичь этого, вот одно такое решение:
_.chain([42,43])
.first(1)
.map(double)
.first()
.value();
// 84
Тем не менее, я бы порекомендовал использовать Равна Тогда с авто-карри и трубкой / составными этими задачами тривиальны:
R.pipe(R.head, R.multiply(2))([42, 43]); // 84
equivalent to:
R.compose(R.multiply(2), R.head)([42, 43]); // 84
Если вы хотите продлить решение, чтобы взять «Сказать первые 2 элемента» вместо одного значения, как запрошено OP, то:
R.pipe(R.take(2), R.map(R.multiply(2)))([42, 43]) // [84, 86]
Однако в Ramda R.com может предпочтительнее. В любом случае, для тривиальных задач, как это, он имеет тенденцию быть более удобным и простым в использовании.
Похоже, Lodash реализован именно то, что вы ищете:
_.thru(value, interceptor)
из документов:
Этот метод похож на _.tap, за исключением того, что он возвращает результат перехвата
Делает map
Работа за это?
_([42, 43]).chain()
.first()
.map(double)
.value()
редактировать
из документации, похоже, map
будет работать только, если вы разместите его до звонка first
:
_([42, 43]).chain()
.map(double)
.first()
.value()
С использованием compose
это еще один способ справиться с ситуацией, но я думаю добавить такую функцию, как take
как я предлагал ранее это лучшее решение.Тем не менее, вот как будет выглядеть код с compose
:
function double(value) { return value * 2; };
_.compose(
double,
_.first,
_.bind(_.identity, _, [42, 43])
)();
Начальное значение должно быть предоставлено через функцию, которая возвращает это значение (здесь это делается путем каррирования identity
), а функции должны быть перечислены в другом, что является противоположностью того, что у вас есть с цепочкой, что мне кажется довольно неестественным.