2012-02-18 14 views
16

Ho un sacco di funzioni utili che ho raccolto durante tutta la mia vita.Come concatenare le funzioni senza utilizzare il prototipo?

function one(num){ 
    return num+1; 
} 

function two(num){ 
    return num+2; 
} 

li posso chiamare con two(two(one(5)))

Ma io preferirei usare (5).one().two().two()

Come posso ottenere questo senza usare prototipo?

Ho provato a vedere come funziona sottolineare catena, ma il loro codice è troppo intenso per capirlo

+1

solo per la cronaca, sì, quelle sono le funzioni che ho raccolto ... – mithril333221

risposta

22

La sintassi del punto è riservata per gli oggetti. Così si può fare qualcosa di simile

function MyNumber(n) { 
    var internal = Number(n); 
    this.one = function() { 
     internal += 1; 
     // here comes the magic that allows chaining: 
     return this; 
    } 
    // this.two analogous 
    this.valueOf = function() { 
     return internal; 
    } 
} 

new MyNumber(5).one().two().two().valueOf(); // 10 

O hai intenzione di implementare questi metodi sul prototipo del numero oggetto/funzione nativa. Che permetterebbe (5).one()...

+0

Ovviamente dovresti implementare anche la cosa 'MyNumber' con i prototipi, perché è molto più efficiente. – Bergi

+0

Il 'valueOf()' è necessario ?, Voglio dire, devo sempre terminare le mie concatenazioni con qualche tipo di funzione che restituisce la val? – mithril333221

+0

@ mithril333221 - per eseguire il concatenamento, il valore restituito da ciascun metodo DEVE essere un oggetto del tipo giusto. Se vuoi qualcosa di diverso da questo fuori dall'oggetto, devi chiamare un metodo per ottenere quelle informazioni. – jfriend00

4

Una bella e generale alternativa è la creazione di una funzione di composizione funzione personalizzata

var go = function(x, fs){ 
    for(var i=0; i < fs.length; i++){ 
     x = fs[i](x); 
    } 
    return x; 
} 

Si può chiamare in questo modo:

go(5, [one, two, two]) 

io non sono personalmente un grande fan di metodo concatenamento poiché limita l'utente a un insieme predefinito di funzioni e vi è una sorta di mancata corrispondenza dell'impedenza tra valori all'interno dell'oggetto "concatenamento" e valori liberi all'esterno.

+0

Voglio sapere quali restrizioni sono – mithril333221

+0

Intendevo dire che se vuoi fare un" metodo di concatenamento ", devi sapere che cosa è tutto concatenabile i metodi saranno quando definirai il chainer (dato che devi aggiungere un metodo al prototipo chainer per ogni funzione). D'altra parte, la versione della composizione delle funzioni non ha bisogno di conoscere le funzioni in anticipo in modo da poter passare tutto ciò che vuoi – hugomg

+0

Ancora, puoi aggiungere funzioni al prototipo ogni volta che ne hai bisogno, il problema è solo che devono inserirsi nel costrutto chainer con 'return this' e usare' this._value'. Lo svantaggio della composizione è che una libreria inquinerebbe lo spazio dei nomi globale e uno spazio dei nomi per riunirli rende più difficile la sintassi della composizione – Bergi

6

Per evitare di dover chiamare toValue alla fine della catena come nella soluzione di @ Bergi, è possibile utilizzare una funzione con metodi allegati. JS chiamerà automaticamente toValue quando proverai a convertirti in un tipo primitivo.

function MyNumber(n) { 
    function x() { } 
    x.one = function() { n++; return this; }; 
    x.valueOf = function() { return n; }; 
    return x; 
} 

Poi,

MyNumber(5).one().one() 
> 7 
0

Un'altra alternativa è di usare lodash flow funzione. Ad esempio:

var five = _.flow(one, two, two) 
five(5) 

Preferisco assegnare una nuova catena a una variabile. Dà un nome chiaro e incoraggia il riutilizzo.

A proposito, lodash aiuta anche a passare argomenti addizionali alle funzioni della catena. Ad esempio:

var addFive = _.flow(
    _.partialRight(_.add, 1), 
    _.partialRight(_.add, 2), 
    _.partialRight(_.add, 2) 
) 

Ci sono molte altre funzioni utili per aiutare a concatenamento funzionale, per esempio, parziale, sviluppa, vibrazione, negate, ecc

Problemi correlati