Domanda

Underscore.js , posso scrivere quanto segue, che ritorna 42:

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

Ho funzione personalizzata, non fa parte della Underscore.js chiamato double():

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

Mi piacerebbe essere in grado di chiamare questa funzione in una catena di sottolineatura, come se fosse parte di sottolineatura. Vorrei scrivere la seguente, che mi piacerebbe 84 ritorno:

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

Questo non può funzionare poiché sottolineatura non definisce double(). Potrei usare tap() come in:

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

Questa è valida, ma tap applica la funzione al suo argomento e restituisce l'argomento, non il risultato della funzione. Così sembra a me come avrei bisogno di una sorta di tap che restituisce il risultato della funzione applicata al suo argomento. C'è qualcosa di simile in Underscore.js? Mi sto perdendo qualcosa di terribilmente ovvio?

È stato utile?

Soluzione

Non trovando un tap che restituisce il valore ritorna dalla funzione è eseguito, mi definiscono quello che posso take e aggiungere al _:

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

Quindi supponendo che ho:

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

Posso scrivere:

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

Si può guardare take come map su oggetti, invece di liste. Vuoi sperimentare con questo? Vedere questo esempio su jsFiddle .

Altri suggerimenti

In modo da avere una funzione personalizzata:

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

È possibile utilizzare mixin di estendere la sottolineatura con esso:

_.mixin({ double:double });

Ora si può chiamare la funzione dall'oggetto _ sottolineatura:

_.double(42); // 84

e dall'oggetto avvolto tornato da chain:

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

Bene, io sono fresco di leggere il codice sorgente di sottolineatura annotato per la prima volta. Ma penso che si può fare qualcosa di simile:

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

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

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

La sintassi / dettagli potrebbe non essere giusto, ma il punto centrale è questo: quando si chiama _([42,43]), si sta chiamando sottolineatura come una funzione. Quando lo fa, si crea un'istanza di un nuovo oggetto e miscele poi in quell'oggetto maggior parte delle funzioni di sottolineatura. Poi, restituisce l'oggetto a voi. È quindi possibile aggiungere le proprie funzioni a tale oggetto, e nessuno di questi inquina il "_" namespace stesso.

Questo è ciò che il codice underscore.js sembrava a me. Se mi sbaglio, mi piacerebbe scoprire e si spera che qualcuno vi spiegherò il perché.

EDIT: Ho effettivamente usando underscore.js pesantemente per circa un mese, e ho ottenuto abbastanza familiarità con esso. Ora so si comporta come ho detto qui. Quando si chiama _ come una funzione di costruzione, si ottiene indietro il proprio "spazio dei nomi" (solo un oggetto), ed è possibile aggiungere le cose ad essa con addToWrapper () che compare nello spazio dei nomi, ma non nel "globale" "_" namespace. Così la funzione il PO voleva è già integrato. (E sono stato veramente colpito con sottolineatura, btw, è molto molto ben fatto).

Molti modi per raggiungere facilmente questo, qui è una soluzione del genere:

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

Tuttavia, mi consiglia di utilizzare Ramda poi con auto-curry e tubi / comporre questi tipi di attività sono banali:

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

equivalent to:

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

Se si voleva estendere la soluzione a prendere dire che i primi 2 elementi, invece di un singolo valore, come richiesto dal PO, allora:

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

Tuttavia, in Ramda R.compose è preferito. In entrambi i casi, per compiti banali come questo, tende ad essere più conveniente e facile da utilizzare.

appare come lodash ha implementato esattamente quello che stai cercando:

_.thru(value, interceptor)

dalla documentazione:

  

Questo metodo è simile a _.tap tranne che restituisce il risultato di   intercettore

https://lodash.com/docs#thru

funziona map per questo?

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

modifica

dalla documentazione, sembra map sarebbe solo lavoro se lo si inserisce prima della chiamata a first:

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

Utilizzando compose è un altro modo affrontare la situazione, ma credo che l'aggiunta di una funzione come take come ho suggerito in precedenza è una soluzione migliore. Eppure, ecco come il codice sarà simile con compose:

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

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

Il valore iniziale deve essere fornita attraverso una funzione che restituisce quel valore (qui fatte da strigliare identity), e le funzioni devono essere elencati in un altro, che è il contrario di quello che hai con una catena, che appare come piuttosto innaturale per me.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top