Подчеркивание.js:как связать пользовательские функции

StackOverflow https://stackoverflow.com/questions/3945673

Вопрос

С использованием 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, за исключением того, что он возвращает результат перехвата

https://lodash.com/docs#ththru.

Делает 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), а функции должны быть перечислены в другом, что является противоположностью того, что у вас есть с цепочкой, что мне кажется довольно неестественным.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top