2014-09-09 23 views
5

Ho una determinata funzione che accetta, tra gli altri argomenti, due argomenti facoltativi che possono essere funzioni. Entrambi devono essere facoltativi, uno sarà una funzione e uno sarà un booleano o una funzione che restituisce un valore booleano.Controllare se la funzione JavaScript ritorna senza eseguirla?

// Obj.func(variable, String[, Object][, Boolean||Function][, Function]); 
Obj.func = function(other, assorted, args, BoolOrFunc, SecondFunc) { 
    // execution 
}; 

Obj.func(
    [ 
     'some', 
     'data' 
    ], 
    'of varying types', 
    { 
     and: 'some optional arguments' 
    }, 
    function() { 
     if(some condition) { 
      return true; 
     } 
     return false; 
    }, 
    function() { 
     // do things without returning 
    } 
); 

E 'mio desiderio che entrambe le funzioni (e diversi altri argomenti, se è importante) essere opzionale, che significa che devo codice nella funzione di determinare quali argomenti l'utente intendeva usare.

Sfortunatamente, poiché entrambe possono essere funzioni e possono essere specificate direttamente nella chiamata di funzione, non è possibile utilizzare semplicemente le condizioni typeof o instanceof. Tuttavia, dal momento che la prima funzione, se esiste, sarà sempre restituire un valore booleano (e la seconda funzione non tornerà affatto), un'idea che avevo sarebbe quello di controllare il suo valore di ritorno:

if(typeof BoolOrFunc === 'boolean' 
    || (typeof BoolOrFunc === 'function' && typeof BoolOrFunc() === 'boolean')) { 
    // BoolOrFunc is either a boolean or a function that returns a boolean. 
    // Handle it as the intended argument. 
} else { 
    // Otherwise, assume value passed as BoolOrFunc is actually SecondFunc, 
    // and BoolOrFunc is undefined. 
} 

Questo funziona in linea di principio; tuttavia, l'esecuzione di typeof BoolOrFunc() esegue la funzione, che causa un problema se la funzione fa più di un semplice ritorno booleano: ovvero se la funzione passata come BoolOrFunc è in realtà destinata allo SecondFunc. SecondFunc, in questo caso, è una specie di funzione di callback e può eseguire azioni, incluse le modifiche DOM, che non desidero eseguire immediatamente.

Per questo motivo, la mia domanda è: C'è un modo per verificare se una funzione ritorna senza eseguirla?

Una cosa che avevo considerato è stato quello di chiamare BoolOrFunc.toString(), poi eseguire una ricerca delle espressioni regolari per il valore di ritorno, qualcosa sulla falsariga di ...

if(typeof BoolOrFunc === 'boolean' 
    || (typeof BoolOrFunc === 'function' 
     && BoolOrFunc.toString().search(/return (true|false);/) !== -1)) { 
    // BoolOrFunc is either a boolean or contains a return string with a boolean. 
    // Handle it as the intended argument. 
} 

Si noti che il codice di cui sopra non può funzionare come scritto: In realtà non ho mai creato un caso di test, perché, beh, sembra eccezionalmente inefficiente e potenzialmente inaffidabile, e ho pensato che qualcuno qui avrebbe potuto trovare una soluzione più elegante al mio dilemma. Detto questo, ho pensato di includerlo a fini di discussione.

+1

Come nota laterale aneddotica, questo è abbastanza vicino al problema di interruzione (http://en.wikipedia.org/wiki/Halting_problem) che è indecidibile su Turing Machines. :) – lexicore

+0

Heh, tiri fuori un buon punto. Probabilmente mi aspetto troppo da JS. : P – Meshaal

+0

Nel caso in cui gli utenti chiamino il modulo che fornisce un valore booleano e una funzione che restituisce un valore booleano, è possibile richiedere invece che passino negli argomenti inclusi in un oggetto, ad es. 'Ob.func (myvar, mystring, myobj, {boolarg: true, funcarg: my_func_that_returns_bool}); 'o qualcosa del genere, per renderlo univoco di cosa si tratta. Quindi l'utente deve assicurarsi che 'my_func_that_returns_bool' faccia come pretende – Brandin

risposta

1

Meshaal ha fatto una previsione nella domanda:

"... one will either be a boolean or a function that returns a boolean." 
"... first function, if it exists, will always return a boolean." 

Con questa previsione la funzione non è una macchina di Turing, perché sappiamo che restituisce qualcosa. Sicuramente non può essere fatto con un semplice RegExp: solo return !0 romperebbe l'esempio.

Ma se si usa il parametro il risultato di function.toString() con un parser sufficientemente intelligente da trovare tutti i possibili punti di restituzione, il problema dovrebbe essere risolvibile principalmente.

0

Interessante domanda, se ho capito bene. In primo luogo, probabilmente avvertirei di non avere argomenti così aperti. Sono curioso riguardo al caso d'uso.

Ma detto questo, è abbastanza facile aggirare i problemi che hai citato (che potrebbero non risolvere completamente il tuo problema).

Questo funziona in linea di principio; tuttavia, l'esecuzione di typeof BoolOrFunc() esegue la funzione ...

Questo è abbastanza facile da risolvere, credo. In un primo momento, controlla se BoolOrFunc è un valore booleano o una funzione (solo typeof BoolOrFunc, natch). Se è un booleano, suppongo che stiamo bene. O SecondFunc manca (undefined) o function - oppure siamo in uno stato di errore. È tutto facile da gestire in questo primo caso.

Quindi supponiamo il secondo caso, che abbiamo BoolOrFunc-As-Function. Dovremo eseguirlo, sia che sia "veramente" BoolOrFuncoSecondFunc, quindi, all'ultimo momento possibile nel tuo codice, fallo.

Questo è ovviamente il punto in cui le cose si complicano senza più pseudo-codice (o codice di produzione) da parte tua. Se "possibile BoolOrFunc" restituisce true o false, si sa che si dispone di una versione di funzione di BoolOrFunc. Se restituisce undefined, sai che hai appena chiamato SecondFunc. Di nuovo, a seconda di cosa stai cercando di fare, ti dirigi qui. Se hai un true o false, devi elaborare "BoolOrFunc-as-function", altrimenti hai chiamato SecondFunc e probabilmente lo farai.

Questo non risponde alla domanda più generica su come dire se una funzione restituisce un tipo specifico senza chiamarlo, ma risolve il caso d'uso come presentato qui.

Ma questo specifico caso più generico [sic] non è troppo difficile, purché si tratti di veri e propri booleani negli return s. In tal caso, la route regexp funzionerebbe: trovare tutto return\s+.*; e assicurarsi che quanto segue ogni return è true o false. O semplicemente confrontare il numero totale return è lo stesso di quello per return\s+(false|true);. O qualcosa. E spero che il javascript nella funzione sia ben formato. Che orso già.

Se la funzione può restituire variabili locali (return MightBeBoolean; piuttosto che return true;), sei quasi toast - o se si accetta o truthiness falsiness, sei quasi brindisi di nuovo, dal momento che è undefined Falsey, e non si può indicare la differenza tra BoolOrFunc o SecondFunc (che restituirebbe sempre "falso"). È possibile, ma non vale la pena scrivere il parser in qualsiasi caso d'uso ragionevole che io possa immaginare. E se stai importando una lib per farlo, sheesh. In bocca al lupo. Sembra che l'eccessivo abbia una funzione leggermente più difensiva nella sua chiamata.

Mi chiedo se entrambe le funzioni siano passate come argomenti sono passati argomenti dal tuo Obj.func, il che renderebbe le cose ancora più interessanti.

Hai più codice reale? ; ^) Ma alla fine ti sto raccomandando di non "passare nessuna confusione di argomenti, a patto che siano in ordine". Penso che si possa probabilmente fare una valutazione tardiva di BoolOrFunc/SecondFunc. Altrimenti, odio dirlo, ma codifica un po 'di più di qui.

Problemi correlati