Question

Utilisation Underscore.js , je peux écrire ce qui suit qui retourne 42:

_([42, 43]).chain()
    .first()
    .value()

Je fonction personnalisée, ne fait pas partie de Underscore.js appelé double():

function double(value) { return value * 2; };

Je voudrais pouvoir appeler cette fonction dans une chaîne Souligné, comme si elle faisait partie de soulignement. Je voudrais écrire ce qui suit, que je voudrais 84 de retour:

_([42, 43]).chain()
    .first()
    .double()
    .value()

Cela peut ne pas fonctionner depuis Souligné ne définit pas double(). Je pourrais utiliser tap() comme dans:

_([42, 43]).chain()
    .first()
    .tap(double)
    .value()

Ceci est valable, mais tap applique la fonction à son argument et renvoie l'argument, et non le résultat de la fonction. Il semble donc à moi comme je aurais besoin d'une sorte de tap qui renvoie le résultat de la fonction appliquée à son argument. Y at-il quelque chose comme ça dans Underscore.js? Suis-je manque quelque chose de terriblement évident?

Était-ce utile?

La solution

Ne pas trouver un tap qui renvoie la valeur revient par la fonction est court, je définir un que je peux take et ajouter à _:

_.mixin({take: function(obj, interceptor) {
    return interceptor(obj);
}});

Ensuite, en supposant que j'ai:

function double(value) { return value * 2; };

Je peux écrire:

_([42, 43]).chain()
    .first()             // 42
    .take(double)        // Applies double to 42
    .value()             // 84

Vous pouvez regarder take comme map sur les objets, au lieu des listes. Vous voulez expérimenter avec cela? Voir cette exemple sur jsFiddle.

Autres conseils

Vous avez donc une fonction personnalisée:

function double(value) { return value * 2; }

Vous pouvez utiliser mixin pour étendre Souligné avec elle:

_.mixin({ double:double });

Maintenant, vous pouvez appeler votre fonction de l'objet Souligné _:

_.double(42); // 84

et de l'objet emballé retourné de chain:

_([42, 43]).chain()
  .first()
  .double() // double made it onto the wrapped object too
  .value(); // 84

D'accord, je suis hors frais de lecture du code source underscore annoté pour la première fois. Mais je pense que vous pouvez faire quelque chose comme ceci:

function double(value) { return value * 2; };

var obj = _([42, 43]).addToWrapper({double:double});

obj.chain()
  .first()
  .double()
  .value();

La syntaxe / détails peut-être pas droit, mais le point de base est la suivante: lorsque vous appelez _([42,43]), vous appelez underscore en fonction. Lorsque vous le faites, il instancie un nouvel objet puis mélanges dans cet objet la plupart des fonctions de soulignement. Ensuite, il retourne cet objet pour vous. Vous pouvez ensuite ajouter vos propres fonctions à cet objet, et rien de tout cela pollue l'espace de noms « _ » lui-même.

C'est ce que le code underscore.js m'a semblé. Si je me trompe, je voudrais savoir et nous espérons que quelqu'un vous expliquer pourquoi.

EDIT: Je suis en fait utilise underscore.js fortement pendant environ un mois maintenant, et je l'ai obtenu assez familier avec elle. Je maintenant sais il se comporte comme je l'ai dit ici. Lorsque vous appelez _ en fonction Constructor, vous récupérez votre propre « espace de noms » (juste un objet), et vous pouvez ajouter des choses à avec addToWrapper () qui apparaissent dans votre espace de noms, mais pas dans le « global » « _ » espace de noms. Ainsi, la fonction de l'OP voulait déjà construit. (Et j'ai été vraiment impressionné par underscore, d'ailleurs, il est très très bien fait).

De nombreux moyens d'atteindre facilement ce, voici une telle solution:

  _.chain([42,43])
    .first(1)
    .map(double)
    .first()
    .value();
    // 84

Cependant, je vous recommande d'utiliser puis avec Ramda auto-curry et tuyau / composent ces types de tâches sont trivial:

R.pipe(R.head, R.multiply(2))([42, 43]);  // 84

equivalent to:

R.compose(R.multiply(2), R.head)([42, 43]);  // 84

Si vous voulez étendre la solution à prendre dire les 2 premiers articles, au lieu d'une seule valeur, tel que demandé par l'OP, alors:

R.pipe(R.take(2), R.map(R.multiply(2)))([42, 43])  // [84, 86]

Cependant, Ramda R.compose est préféré. De toute façon, pour des tâches triviales comme celle-ci, elle a tendance à être plus pratique et facile à utiliser.

On dirait lodash a mis en place exactement ce que vous cherchez:

_.thru(value, interceptor)

de la documentation:

  

Cette méthode est comme _.tap sauf qu'il renvoie le résultat de   intercepteur

https://lodash.com/docs#thru

Est-ce que le travail de map pour cela?

_([42, 43]).chain()
    .first()
    .map(double)
    .value()

modifier

de la documentation, il semble que map ne fonctionne que si vous placez avant l'appel à first:

_([42, 43]).chain()
    .map(double)
    .first()
    .value()

L'utilisation compose est une autre façon face à la situation, mais je pense que l'ajout d'une fonction telle que take comme je l'ai suggéré plus tôt est une meilleure solution. Pourtant, voici comment le code ressemblerait à compose:

function double(value) { return value * 2; };

_.compose(
    double,
    _.first,
    _.bind(_.identity, _, [42, 43])
)();

La valeur initiale doit être fournie par une fonction qui renvoie cette valeur (ici faite par taitement identity), et les fonctions doivent figurer dans un autre qui est l'inverse de ce que vous avez avec une chaîne, qui apparaît comme assez naturel pour moi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top