2015-05-04 13 views
8

Sto cercando una soluzione vanilla JavaScript.Argomenti della funzione JavaScript: posizionale -> transizione della mappa

dire che ho avuto una funzione con la seguente intestazione:

generateEmail(firstName, lastname, provider) 

ho bisogno di correre in questo modo:

generateEmail("John","Smith","gmail.com"); 

Vorrei essere in grado di chiamare con argomento mappare invece di argomenti posizionali, cioè

generateEmail({ 
    "firstName":"John", 
    "lastname": "Smith", 
    "provider": "gmail.com" 
}); 

E sto cercando una soluzione già scritta per farlo in JavaScript, dal momento che ho un numero illimitato di funzioni come generateEmail sopra per gestire. Esiste una tale biblioteca?

Ho visto https://github.com/kilianc/node-introspect che gestisce l'introspezione (informazioni sui parametri astratti di ritorno). Ma manca la seconda parte: mappatura della mappa chiamata in chiamata di posizione.

Per favore dimmi, se tale cosa esiste.


modifica: se non mi sono chiaro: non desidero modificare la funzione di argomento posizionale originale. Ottengo tali funzioni da un fornitore esterno che può aggiornare il suo codice. Preferirei preferire un wrapper in grado di richiamare la funzione originale al di sotto e fornire all'esterno un'API map-argument.

+0

È possibile verificare se 'firstName' è un oggetto e quindi chiamare' generateEmail' nuovamente con argomenti appropriati. –

+1

@GaurangTandon questo è completamente ciò di cui non ho ** bisogno **.Ho bisogno di una funzione wrapper generica che gestisca ciò che ho scritto. Posso scriverlo da solo, ma prima voglio controllare, se già esiste una cosa del genere. – ducin

+0

Direi usando una combinazione di questo http://stackoverflow.com/questions/914968/inspect-the-names-values-of-arguments-in-the-definition-execution-of-a-javascrip e '. applicare »questo sarebbe possibile. –

risposta

3

Supponendo di avere accesso a introspect da node-introspect (che prende una funzione e restituisce un elenco ordinato di nomi argomenti), si può semplicemente fare:

function objArgsify(fn) { 
    var argNames = introspect(fn); 
    return function(obj) { 
     return fn.apply(this, 
         argNames.map(function(a) { return obj[a]; }); 
    } 
} 

lo chiamano da:

var generateEmailWithObjArgs = objArgsify(generateEmail); 
generateEmailWithObjArgs({ 
    "firstName":"John", 
    "lastname": "Smith", 
    "provider": "gmail.com" 
}); 

Questo accetta una funzione, legge i suoi nomi argomento e quindi restituisce una funzione wrapper che accetta un oggetto e utilizza i nomi degli argomenti posizionali per estrarre le proprietà dall'argomento oggetto nell'ordine corretto.

Questa funzione utilizza l'argomento dell'oggetto tempo di chiamata come una mappa per trasformare l'array ["firstName", "lastname", "provider"] nell'array ["John", "Smith", "gmail.com"]. Quella matrice viene quindi utilizzata con apply per richiamare la funzione argomento-posizionale.

+0

Molto più ordinato della mia soluzione. –

+0

Speravo che ci fosse una libreria che la gestisse, non volevo reinventare la ruota. Ad ogni modo, la tua soluzione mira ai miei bisogni; Stavo pensando di più: 'var argMapify = function (fn, argValues, context) { var argDefs = introspect (fn); return fn.apply (context, argDefs.map (function (arg) { return argValues ​​[arg]; })); } e chiamando 'argMapify (fn, {...})', perché si ottiene la funzione da un fornitore esterno e si chiama la funzione al volo. – ducin

+1

Fare attenzione con l'uso di 'node-introspect' perché sta analizzando una funzione come una stringa. Qualcosa che cade al di fuori della sua espressione regolare (qui in futuro, abbiamo le funzioni di freccia a singolo argomento ES6 con parentesi opzionali) non riuscirà ad analizzare. In breve, fai attenzione se stai considerando questo nel mondo reale. – davidjb

0

Qualcosa di simile

var orig_generateEmail = generateEmail; 
    var generateEmail = function (map) { 
       orig_generateEmail(map.firstName, map.lastname, map.provider); 
    }; 

Ma che finisce, ovviamente, in una lista di "mapping" statici.

2

senza l'utilizzo di librerie esterne,

var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; 
var ARGUMENT_NAMES = /([^\s,]+)/g; 
function getParamNames(func) { 
    var fnStr = func.toString().replace(STRIP_COMMENTS, ''); 
    var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); 
    if(result === null) 
    result = []; 
    return result; 
} 

function call(method, object) { 
    var params = getParamNames(method); 
    var arrParams = []; 
    for (var i = 0; i < params.length; i++) { 
     arrParams.push(object[params[i]]); 
    } 
    return method.apply(arrParams); 
} 

Basta chiamare con call(generateEmail, generateEmailObject).

Problemi correlati