Più argomenti vs opzioni oggetto

Durante la creazione di una funzione JavaScript con più argomenti, sono sempre di fronte a questa scelta: passare un elenco di argomenti contro il passaggio di un oggetto opzioni.

Per esempio sto scrivendo una funzione di mappa di una nodeList di un array:

function map(nodeList, callback, thisObject, fromIndex, toIndex){
    ...
}

Potrei invece usare questo:

function map(options){
    ...
}

in cui le opzioni è un oggetto:

options={
    nodeList:...,
    callback:...,
    thisObject:...,
    fromIndex:...,
    toIndex:...
}

Qual è il modo consigliato? Ci sono delle linee guida per l’utilizzo di uno contro l’altro?

[Aggiornamento] sembra che Ci sia un consenso a favore delle opzioni oggetto, vorrei aggiungere un commento: una ragione per cui ho avuto la tentazione di utilizzare l’elenco di argomenti nel mio caso era quello di avere un comportamento coerente con il JavaScript costruito in array.metodo della mappa.

La seconda opzione permette di argomenti denominati, che è una cosa bella a mio parere.
Sono facoltativi o obbligatori argomenti?
nel mio esempio gli ultimi tre sono opzionali.
Perché i tuoi ultimi due argomenti sono molto simili, se l’utente passato solo uno o l’altro, non si può mai veramente essere in grado di sapere quale era destinato. Per questo motivo, si sarebbe quasi bisogno di argomenti denominati. Ma apprezzo che ci si vuole mantenere un API simili alle API native.
Modellazione dopo l’API nativa non è una brutta cosa, se la funzione fa qualcosa di simile. Tutto si riduce a “ciò che rende il codice più readablae.” Array.prototype.map ha una semplice API, che non dovrebbe lasciare semi-esperto programmatore sconcertante.

OriginaleL’autore Christophe | 2012-10-10

10 risposte

  1. 111

    Come tanti altri, spesso preferisco il passaggio di un options object di una funzione invece di passare un lungo elenco di parametri, ma in realtà dipende dal contesto.

    Io uso la leggibilità del codice, come la cartina di tornasole.

    Per esempio, se ho questa chiamata di funzione:

    checkStringLength(inputStr, 10);

    Penso che il codice è abbastanza leggibile il modo in cui è e il passaggio di parametri individuali è solo bene.

    D’altra parte, ci sono funzioni di chiamate come questo:

    initiateTransferProtocol("http", false, 150, 90, null, true, 18);

    Completamente illeggibile a meno che voi fare qualche ricerca. D’altra parte, questo codice si legge bene:

    initiateTransferProtocol({
      "protocol": "http",
      "sync":      false,
      "delayBetweenRetries": 150,
      "randomVarianceBetweenRetries": 90,
      "retryCallback": null,
      "log": true,
      "maxRetries": 18
     });

    È più un’arte che una scienza, ma se dovessi nome rules of thumb:

    Utilizzare un parametro options se:

    • Si dispone di più di quattro parametri
    • Tutti i parametri sono opzionali
    • Hai mai avuto a cercare la funzione di capire quali parametri prende
    • Se qualcuno prova mai a strangolare mentre urla “ARRRRRG!”
    Grande risposta. Dipende. Attenzione boolean trappole ariya.ofilabs.com/2011/08/hall-of-api-shame-boolean-trap.html
    Oh, sì… avevo dimenticato che il collegamento. E ‘ davvero mi ha fatto ripensare a come le Api lavoro e ho anche riscritto diversi pezzi di codice dopo aver imparato l’ho fatto cose stupide. Grazie!
    Non legati molto, ma per quanto riguarda in linguaggi come C#, dove ci sono i parametri con nome e potrebbe apparire come InitiateTransferProtocol(protocol: "http", sync: false, .... ?
    Se y’all sono interessati alle conseguenze sulle prestazioni di questo bit di codifica best practices’, ecco un jsPerf prova in entrambi i modi: jsperf.com/function-boolean-arguments-vs-options-object/10 Nota la piccola torsione nella terza alternativa, dove io uso un ‘preset’ (costante) opzioni oggetto, che può essere fatto quando hai molte chiamate (durante il ciclo di vita di runtime, ad esempio, la vostra pagina web) con le stesse impostazioni, noto al tempo di sviluppo (in breve: quando la vostra opzione, i valori sono un pò hardcoded nel codice sorgente).
    grazie per questo: “Non è più un’arte che una scienza” e “io uso la leggibilità del codice, come la cartina di tornasole.” e “Se qualcuno prova mai a strangolare mentre urla “ARRRRRG!””

    OriginaleL’autore Jeremy J Starcher

  2. 23

    Più argomenti sono per lo più per i parametri obbligatori. Non c’è niente di sbagliato con loro.

    Se si dispone di parametri opzionali, è complicato. Se uno di loro si basa su altre, in modo che essi hanno un certo ordine (ad esempio, il quarto esigenze il terzo), è ancora necessario utilizzare più argomenti. Quasi tutti i nativi EcmaScript e DOM-metodi di lavoro come questo. Un buon esempio è il metodo di XMLHTTPrequestsdove gli ultimi 3 argomenti sono facoltativi – la regola è come “nessuna password senza che l’utente” (vedi anche MDN docs).

    Oggetti tornare utile in due casi:

    • Hai tanti parametri che crea confusione: Il “naming” vi aiuto, non devono preoccuparsi circa l’ordine di loro (soprattutto se si può cambiare)
    • Hai i parametri opzionali. Gli oggetti sono molto flessibili, e senza alcun ordine, è sufficiente passare le cose che avete bisogno e niente altro (o undefineds).

    Nel tuo caso, ti consiglio di map(nodeList, callback, options). nodelist e callback sono obbligatori, gli altri tre argomenti entrare solo di tanto in tanto e hanno valori di default ragionevoli.

    Un altro esempio è JSON.stringify. Si potrebbe desiderare di utilizzare il space parametro senza il passaggio di un replacer funzione per chiamare …, null, 4). Argomenti oggetto potrebbe essere migliore, anche se la sua non è davvero ragionevole per solo 2 parametri.

    +1 domanda @trevor-dixon: hai visto questo mix utilizzato in pratica, per esempio nelle librerie js?
    Un esempio potrebbe essere jQuery metodi ajax. Essi accettano la [obbligatorio] URL come primo argomento, e un grande argomento di opzioni come il secondo.
    in modo strano! Io non l’ho mai notato prima. Ho sempre visto utilizzato con l’url come opzione proprietà…
    Sì, jQuery cosa strana con i suoi parametri opzionali durante la permanenza compatibile 🙂
    A mio parere, questo è l’unico sano di mente di rispondere qui.

    OriginaleL’autore Bergi

  3. 11

    Utilizzando le opzioni come oggetto’ approccio sta per essere migliore. Non è necessario preoccuparsi circa l’ordine delle proprietà e c’è di più flessibilità in quali dati viene passato (parametri opzionali per esempio)

    La creazione di un oggetto significa anche opzioni potrebbe essere facilmente utilizzato in molteplici funzioni:

    options={
        nodeList:...,
        callback:...,
        thisObject:...,
        fromIndex:...,
        toIndex:...
    }
    
    function1(options){
        alert(options.nodeList);
    }
    
    function2(options){
        alert(options.fromIndex);
    }
    +1 punto sul riutilizzo di oggetti tra le varie funzioni.
    La (ragionevole) presupposto è che l’oggetto avrà sempre la stessa coppia di chiavi. Se stai lavorando con una merda/incoerente API allora hai un problema sulle vostre mani.

    OriginaleL’autore Fluidbyte

  4. 8

    Credo che se sei istanziare qualcosa o chiamare un metodo di un oggetto, si desidera utilizzare un oggetto opzioni. Se è una funzione che opera su uno o due parametri e restituisce un valore, un elenco di argomenti è preferibile.

    In alcuni casi, è bene usare entrambi. Se la funzione ha uno o due parametri obbligatori e un sacco di optional, fanno i primi due parametri richiesti ed il terzo opzionale opzioni di hash.

    Nel tuo esempio, mi piacerebbe fare map(nodeList, callback, options). Nodelist e di callback sono necessari, è abbastanza facile capire cosa sta accadendo proprio dalla lettura di una chiamata, ed è come una mappa esistente funzioni. Tutte le altre opzioni possono essere passati come terzo parametro opzionale.

    +1 penso che questo sia un buon equilibrio alternativa.
    +1 interessante. Avete visto utilizzato in pratica, per esempio nelle librerie js?

    OriginaleL’autore Trevor Dixon

  5. 6

    Il tuo commento sulla questione:

    nel mio esempio gli ultimi tre sono opzionali.

    Quindi perché non farlo? (Nota: Questo è abbastanza crudo Javascript. Normalmente mi piacerebbe utilizzare un default hash e di aggiornamento con le opzioni passato utilizzando Oggetto.estendere o JQuery.estendere o simili..)

    function map(nodeList, callback, options) {
       options = options || {};
       var thisObject = options.thisObject || {};
       var fromIndex = options.fromIndex || 0;
       var toIndex = options.toIndex || 0;
    }

    Così, ora, dal momento che ora è molto più evidente ciò che è facoltativo e cosa non lo è, tutti questi sono valide utilizza la funzione:

    map(nodeList, callback);
    map(nodeList, callback, {});
    map(nodeList, callback, null);
    map(nodeList, callback, {
       thisObject: {some: 'object'},
    });
    map(nodeList, callback, {
       toIndex: 100,
    });
    map(nodeList, callback, {
       thisObject: {some: 'object'},
       fromIndex: 0,
       toIndex: 100,
    });
    Questo è simile a @trevor-dixon risposta.

    OriginaleL’autore Izkata

  6. 3

    Dipende.

    In base alla mia osservazione su quelle biblioteche popolari di disegno, qui sono gli scenari che si deve usare l’opzione oggetto:

    • Il parametro lista è lunga (>4).
    • Alcuni o tutti i parametri sono opzionali e non si basano su un certo
      ordine.
    • L’elenco dei parametri, potrebbe crescere in futuro API di aggiornamento.
    • L’API sarà chiamato da un altro codice e il nome di API non è chiaro
      basta raccontare i parametri di significato. Così si potrebbe bisogno di un forte
      nome del parametro per migliorare la leggibilità.

    E scenari per l’utilizzo di un elenco di parametri

    • Elenco dei parametri è breve (<= 4).
    • La maggior parte o tutti i parametri necessari.
    • I parametri opzionali sono in un certo ordine. (cioè: $.get )
    • Facile dire i parametri di significato con il nome di API.

    OriginaleL’autore Lynn Ning

  7. 2

    Oggetto è più preferibile, perché se si passa un oggetto semplice per estendere il numero di proprietà che gli oggetti e non si deve guardare per l’ordine in cui gli argomenti è stato superato.

    OriginaleL’autore happyCoda

  8. 2

    Posso essere un po ‘ in ritardo alla festa, con questa risposta, ma ero alla ricerca di altri sviluppatori opinioni su questo argomento e sono imbattuto in questo thread.

    Sono molto d’accordo con la maggior parte dei soccorritori, e il lato con il ‘più argomenti”. Il mio argomento principale è che non si scoraggia altri anti-pattern come “la mutazione e la restituzione del param oggetto”, o “passare lo stesso param oggetto ad altre funzioni”. Ho lavorato in due codici che hanno ampiamente abusato di questo anti-pattern, e il debug di codice che fa questo diventa presto impossibile. Penso che questo è un Javascript specifici di regola, dal momento che Javascript non è fortemente tipizzato e consente il arbitrariamente oggetti strutturati.

    Mia opinione personale è che gli sviluppatori dovrebbero essere esplicito, quando le funzioni di chiamata, di evitare di passare tutto ridondante di dati e di evitare di modificare per riferimento. Non è che questo pattern preclude la scrittura concisa, il codice corretto. Mi sento solo rende molto più facile per il vostro progetto di cadere in cattive pratiche di sviluppo.

    Si consideri il seguente codice terribile:

    function main() {
        const x = foo({
            param1: "something",
            param2: "something else",
            param3: "more variables"
        });
    
        return x;
    }
    
    function foo(params) {
        params.param1 = "Something new";
        bar(params);
        return params;
    }
    
    
    function bar(params) {
        params.param2 = "Something else entirely";
        const y = baz(params);
        return params.param2;
    }
    
    function baz(params) {
        params.params3 = "Changed my mind";
        return params;
    }

    Non solo questo tipo di richiedere più esplicito documentazione per specificare intenti, ma che lascia anche spazio per vago errori.
    Che cosa succede se uno sviluppatore modifica param1 in bar()? Quanto tempo pensi che vorresti prendere guardando attraverso una codebase di sufficident dimensioni per la cattura di questo?
    Certo, questo è un esempio è leggermente ipocrita perché si presuppone che gli sviluppatori hanno già commesso diversi anti-pattern da questo punto. Ma che mostra come il passaggio di oggetti contenenti parametri permette un maggiore spazio per gli errori e ambiguità, che richiedono un maggior grado di consapevolezza e di rispetto delle const correttezza.

    Solo i miei due cents sulla questione!

    OriginaleL’autore ajxs

  9. 1

    Per una funzione che di solito utilizza alcuni argomenti predefiniti è meglio usare l’opzione oggetto. L’esempio opposto sarà qualcosa di simile a una funzione che è sempre un numero infinito di argomenti come: setCSS({height:100},{width:200},{background:”#000″}).

    OriginaleL’autore Ilya Sidorovich

  10. 0

    Vorrei guardare grande javascript progetti.

    Cose come mappa di google di frequente di vedere che oggetti istanziati richiedono un oggetto, ma è necessario per le funzioni parametri. Vorrei che questo ha a che fare con OPZIONE argumemnts.

    Se avete bisogno di argomenti di default o argomenti facoltativi di un oggetto probabilmente sarebbe meglio, perché è più flessibile. Ma se non è normale funzionale argomenti sono più espliciti.

    Javascript ha un arguments oggetto troppo.
    https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments

    OriginaleL’autore dm03514

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *