Frage

Mit Underscore.js , kann ich folgendes schreiben, die 42 zurückgibt:

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

Ich habe benutzerdefinierte Funktion, die nicht Teil von Underscore.js genannt double():

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

Ich möchte in der Lage sein, diese Funktion in einer Unders Kette zu nennen, als ob es Teil Unders war. Ich möchte folgende schreiben, die ich Rückkehr 84 möchten:

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

Das kann nicht da Unders funktioniert nicht double() definieren. Ich konnte verwenden tap() wie in:

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

Dies ist gültig, aber tap wendet die Funktion auf ihr Argument und gibt das Argument, nicht das Ergebnis der Funktion. So sieht es aus mir, wie ich eine Art tap brauchen würde, dass die Renditen das Ergebnis der Funktion auf ihr Argument angewendet. Gibt es so etwas wie dies in Underscore.js? Bin ich etwas fehlt schrecklich offensichtlich?

War es hilfreich?

Lösung

Nicht ein tap dass kehrt der Wert wieder durch die Funktion zu finden ist, läuft, und ich habe zu definieren, die ich take _ und hinzufügen:

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

Dann unter der Annahme, ich habe:

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

Ich kann schreiben:

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

Sie können sich auf Objekte in take als map aussehen, anstatt von Listen. Wollen Sie damit experimentieren? Sehen Sie dieses Beispiel auf jsFiddle .

Andere Tipps

So haben Sie eine benutzerdefinierte Funktion haben:

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

Sie können mit mixin Unders erweitern damit:

_.mixin({ double:double });

Jetzt können Sie Ihre Funktion vom Objekt _ Unders nennen:

_.double(42); // 84

und von dem umwickelten Gegenstand von chain zurückgegeben:

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

In Ordnung, ich bin frisch aus den Unterstrich kommentierte Quelltext zum ersten Mal zu lesen. Aber ich denke, Sie so etwas tun kann:

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

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

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

Die Syntax / Details möglicherweise nicht richtig sein, aber der Kern Punkt ist: Wenn Sie _([42,43]) nennen, sind Sie Strich als Funktion aufrufen. Wenn Sie dies tun, instanziiert es ein neues Objekt und dann mischt in diesem Objekt die meisten der Unterstrich-Funktionen. Dann kehrt es das Objekt für Sie. Sie können Ihre eigenen Funktionen für das Objekt, und keiner dieser verpestet die „_“ Namensraum selbst dann hinzuzufügen.

Das ist, was der Underscore.js Code wie ich aussieht. Wenn ich falsch bin, würde Ich mag, um herauszufinden, und hoffentlich wird jemand erklären, warum.

EDIT: Ich habe jetzt eigentlich schon Underscore.js stark für etwa einen Monat mit, und ich habe ziemlich vertraut mit ihm bekommen. Ich jetzt wissen es verhält sich wie ich hier gesagt. Wenn Sie _ als Constructor-Funktion aufrufen, erhalten Sie Ihren eigenen „Namensraum“ zurück (nur ein Objekt), und man kann die Dinge, um es mit addToWrapper () hinzufügen, die in Ihrem Namensraum zeigen sich aber nicht in der „global“ „_“ Namespace. So ist die Funktion wollte die OP bereits eingebaut ist. (Und ich habe btw mit Unterstrich, wirklich beeindruckt, es ist sehr, sehr schön gemacht).

Viele Möglichkeiten, um dies leicht zu erreichen, hier ist eine solche Lösung:

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

Allerdings würde ich empfehlen die Verwendung von Ramda dann mit auto-Curry und Rohr / compose diese Arten von Aufgaben sind trivial:

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

equivalent to:

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

Wenn Sie die Lösung erweitern wollen die ersten 2 Artikel sagen zu nehmen, statt einem einzigen Wert, wie die OP angefordert, dann:

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

Doch in Ramda R.compose bevorzugt. So oder so, für triviale Aufgaben wie diese, es neigt bequemer und einfach zu bedienen sein.

Sieht aus wie lodash hat genau das umgesetzt, was Sie suchen:

_.thru(value, interceptor)

aus der Dokumentation:

Diese Methode ist wie _.tap außer dass es gibt das Ergebnis der Abfangjäger

https://lodash.com/docs#thru

Does map Arbeit für das?

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

Bearbeiten

aus der Dokumentation, es sieht aus wie map würde nur funktionieren, wenn Sie es vor dem Aufruf von first platzieren:

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

compose Verwendung ist eine andere Art und Weise mit der Situation zu tun, aber ich denke, eine Funktion wie take Hinzufügen , wie ich früher vorgeschlagen ist eine bessere Lösung. Dennoch ist hier, wie der Code wie mit compose aussehen:

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

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

Der Anfangswert muss über eine Funktion zur Verfügung gestellt werden die Erträge dieser Wert (hier erfolgt durch identity currying) und die Funktionen müssen in einer anderen aufgeführt werden, die das Gegenteil dessen, was man mit einer Kette, die als erscheint ziemlich unnatürlich für mich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top