Skip to content
Fetching latest commit…
Cannot retrieve the latest commit at this time.
..
Failed to load latest commit information.
readme.md

readme.md

Princìpi per la scrittura di JavaScript consistente ed idiomatico

Questo è un documento sempre in continua evoluzione e nuove idee per migliorare il codice che ci circonda sono sempre le benvenute. Contribuisci: fork, clone, branch, commit, push, pull request.

Tutto il codice in qualsiasi linguaggio dovrebbe sembrare come scritto da una singola persona, non importa quante persone vi abbiano contribuito.

Il seguente elenco, evidenzia le pratiche che utilizzo in tutto il codice di cui sono l'autore originale; contributi ai progetti da me creati dovrebbero seguire queste linee guida.

Non è mia intenzione imporre il mio stile sul codice altrui; se gli altri hanno già uno stile esistente che seguono - questo dovrebbe essere rispettato.

"Parte dell'essere un buon amministratore per un progetto di successo è capire che la scrittura di codice per sé stessi è una Cattiva Idea™. Se migliaia di persone usano il tuo codice, allora scrivi il tuo codice in modo che abbia la massima chiarezza, e non seguendo i tuoi gusti personali su come renderlo chiaro all'interno delle specifiche" - Idan Gazit

Traduzioni

Cose importanti, non idiomatiche:

Qualità del codice: Ottimi strumenti, Risorse e Guide

Leveraging Code Quality Tools di Anton Kovalyov

Impara

http://es5.github.com/

I seguenti dovrebbero essere considerati come 1) incompleti e 2) DA LEGGERE. Non sempre sono d'accordo con lo stile scritto dagli autori qui sotto, ma una cosa è certa: Sono consistenti. Quindi, sono autorità per questo linguaggio.

Processo di costruzione e distribuzione

I progetti dovrebbero sempre cercare di includere qualche mezzo generico per il quale il sorgente possa essere validato (linted), testato e compresso in preparazione per l'uso in produzione. Per questo lavoro, grunt di Ben Alman non è secondo a nessuno e ha ufficialmente rimpiazzato la directory "kits/" di questo repo.

Processo di test

I progetti devono includere una qualche sorta di unità, guida o implementazione di test oppure un test funzionale. Le dimostrazioni di casi d'uso NON SI QUALIFICANO come "test". La seguente è una lista di framework per il testing, nessuno dei quali è preferito rispetto all'altro.

Tavola dei contenuti


Prefazione

Le seguenti sezioni evidenziano una ragionevole guida di stile per lo sviluppo moderno di JavaScript, e non sono intese per essere obbligatorie. Il concetto più importante è la legge sulla consistenza dello stile del codice. Qualsiasi stile scegliate per i vostri progetti dovrebbe essere considerato legge. Potete mettere un link a questo documento come espressione di impegno alla consistenza, leggibilità e manutenibilità del codice del vostro progetto.

Manifesto dello stile idiomatico

  1. Spazio vuoto

    • Mai mischiare spazi e tabulazioni.
    • Quando iniziate un progetto, prima di scrivere qualsiasi codice, scegliete tra indentazione soft (spazi) o tabulazioni reali, considerate questo legge.
      • Per la leggibilità, raccomando sempre di impostare la dimensione di indentamento del proprio editor a due caratteri — questo significa, due spazi o due spazi rappresentanti una tabulazione reale.
    • Se il vostro editor lo supporta, lavorate sempre con l'impostazione "mostra caratteri invisibili" attiva. I benefici di questa pratica sono:
      • Rafforzata consistenza
      • Eliminazione di spazi vuoti alla fine delle linee
      • Eliminazione di linee vuote
      • Commit e diff più facili da leggere
  2. Bella sintassi

    A. Parentesi, parentesi graffe, interruzioni di linea

    // if/else/for/while/try hanno sempre spazi, parentesi graffe e sono suddivisi su 
    // più linee questo incoragga la leggibilità
    
    // 2.A.1.1
    // Esempi di sintassi veramente illeggibile
    
    if(condition) doSomething();
    
    while(condition) iterating++;
    
    for(var i=0;i<100;i++) someIterativeFn();
    
    
    // 2.A.1.1
    // Uso degli spazi vuoti per incrementare la leggibilità
    
    if ( condition ) {
      // istruzioni
    }
    
    while ( condition ) {
      // istruzioni
    }
    
    for ( var i = 0; i < 100; i++ ) {
      // istruzioni
    }
    
    // Ancora meglio:
    
    var i,
      length = 100;
    
    for ( i = 0; i < length; i++ ) {
      // istruzioni
    }
    
    // Oppure...
    
    var i = 0,
      length = 100;
    
    for ( ; i < length; i++ ) {
      // istruzioni
    }
    
    var prop;
    
    for ( prop in object ) {
      // istruzioni
    }
    
    
    if ( true ) {
      // istruzioni
    } else {
      // istruzioni
    }

    B. Assegnazioni, dichiarazioni, funzioni ( nominata, espressione, costruttore )

    // 2.B.1.1
    // Variabili
    var foo = "bar",
      num = 1,
      undef;
    
    // Notazioni literal:
    var array = [],
      object = {};
    
    
    // 2.B.1.2
    // L'utilizzo di solo una `var` per scope (funzione) incrementa la leggibilità
    // e mantiene la tua lista di dichiarazioni ordinata (inoltre riduce il numero di digitazioni)
    
    // Sbagliato
    var foo = "";
    var bar = "";
    var quux;
    
    // Corretto
    var foo = "",
      bar = "",
      quux;
    
    // oppure...
    var // Commento su questa linea
    foo = "",
    bar = "",
    quux;
    
    // 2.B.1.3
    // le dichiarazioni var dovrebbero sempre essere all'inizio del rispettivo scope (funzione).
    // Lo stesso vale per const e let di ECMAScript 6.
    
    // Sbagliato
    function foo() {
    
      // del codice qui
    
      var bar = "",
        qux;
    }
    
    // Corretto
    function foo() {
      var bar = "",
        qux;
    
      // tutto il codice dopo le dichiarazioni delle variabili.
    }
    // 2.B.2.1
    // Dichiarazione di funzione nominata
    function foo( arg1, argN ) {
    
    }
    
    // Utilizzo
    foo( arg1, argN );
    
    
    // 2.B.2.2
    // Dichiarazione di funzione nominata
    function square( number ) {
      return number * number;
    }
    
    // Utilizzo
    square( 10 );
    
    // Stile di prosecuzione nel passaggio piuttosto artificioso
    function square( number, callback ) {
      callback( number * number );
    }
    
    square( 10, function( square ) {
      // codice di callback
    });
    
    
    // 2.B.2.3
    // Funzione espressione
    var square = function( number ) {
      // Ritorna qualcosa di valutabile e rilevante
      return number * number;
    };
    
    // Funzione espressione con identificatore
    // Questa forma preferita ha il valore aggiunto di essere in grado
    // di chiamare sé stessa ed ha un'identità nelle tracce dello stack:
    var factorial = function factorial( number ) {
      if ( number < 2 ) {
        return 1;
      }
    
      return number * factorial( number-1 );
    };
    
    
    // 2.B.2.4
    // Dichiarazione di costruttore
    function FooBar( options ) {
    
      this.options = options;
    }
    
    // Utilizzo
    var fooBar = new FooBar({ a: "alpha" });
    
    fooBar.options;
    // { a: "alpha "}

    C. Eccezioni, lievi deviazioni

    // 2.C.1.1
    // Funzioni con callback
    foo(function() {
      // Nota che non c'è spazio aggiuntivo tra la prima parentesi
      // della funzione chiamata in esecuzione e la parola "function"
    });
    
    // Funzione che accetta un array, nessuno spazio
    foo([ "alpha", "beta" ]);
    
    // 2.C.1.2
    // Funzione che accetta un oggetto, nessuno spazio
    foo({
      a: "alpha",
      b: "beta"
    });
    
    // Singolo argomento literal stringa, nessuno spazio
    foo("bar");
    
    // Parentesi interne di raggruppamento, nessuno spazio
    if ( !("foo" in obj) ) {
    
    }
    

    D. La consistenza vince sempre

    Nelle sezioni 2.A-2.C, le regole per lo spazio vuoto vengono stabilite come raccomandazione con uno scopo semplice ed importante: la consistenza. È importante notare che le preferenze di formattazione, come lo "spazio vuoto interno" dovrebbero essere considerate opzionali, ma solo uno stile dovrebbe esistere per l'intero sorgente del vostro progetto.

    // 2.D.1.1
    
    if (condition) {
      // dichiarazioni
    }
    
    while (condition) {
      // dichiarazioni
    }
    
    for (var i = 0; i < 100; i++) {
      // dichiarazioni
    }
    
    if (true) {
      // dichiarazioni
    } else {
      // dichiarazioni
    }
    

    E. Apici

    Sia che preferiate singoli o doppi apici non importa, non c'è differenza di gestione da parte di JavaScript. Ciò che DEVE ASSOLUTAMENTE essere mantenuta è la consistenza. Mai mischiare gli apici nello stesso progetto. Scegliete uno stile e proseguite con esso.

    F. Fine delle linee e linee vuote

    Lo spazio vuoto può complicare le diff e rendere le modifiche impossibili da leggere. Considerate di implementare un hook di pre-commit che rimuova automaticamente lo spazio vuoto alla fine delle linee e gli spazi vuoti nelle linee vuote.

  3. Controllo dei tipi (offerto dalle linee guida della jQuery Core Style)

    A. Tipi attuali

    Stringa:

    typeof variable === "string"
    

    Numero:

    typeof variable === "number"
    

    Booleano:

    typeof variable === "boolean"
    

    Oggetto:

    typeof variable === "object"
    

    Matrice:

    Array.isArray( arrayLikeObject )
    (dove possibile)
    

    Nodo:

    elem.nodeType === 1
    

    Nullo:

    variable === null
    

    Nullo o non definito (undefined):

    variable == null
    

    Non definito:

    Variabili globali:

    typeof variable === "undefined"
    

    Variabili locali:

    variable === undefined
    

    Proprietà:

    object.prop === undefined
    object.hasOwnProperty( prop )
    "prop" in object
    

    B. Tipi forzati

    Considerate le implicazioni del seguente...

    Dato questo HTML:

    <input type="text" id="foo-input" value="1">
    
    // 3.B.1.1
    
    // `foo` è stato dichiarato con il valore '0' ed il suo tipo è `number`
    var foo = 0;
    
    // typeof foo;
    // "number"
    ...
    
    // Successivamente, in qualche altra parte del codice, necessitate di aggiornare `foo`
    // con un nuovo valore derivato da un elemento input
    
    foo = document.getElementById("foo-input").value;
    
    // Se testaste `typeof foo` adesso, il risultato sarebbe `string`
    // Ciò significa che se aveste del codice che testa `foo` in questo modo:
    
    if ( foo === 1) {
    
      importantTask();
    
    }
    
    // `importantTask()` non verrebbe mai eseguito, anche se `foo` avesse valore di "1"
    
    
    // 3.B.1.2
    
    // Potete prevenire questi problemi usando la forzatura intelligente con gli operatori unari + o -:
    
    foo = +document.getElementById("foo-input").value;
    //    ^ l'operatore + unario convertirà il suo operando a destra in un numero
    
    // typeof foo
    // "number"
    
    if ( foo === 1 ) {
    
      importantTask();
    
    }
    
    // `importantTask()` verrà eseguito

    Ecco alcuni casi comuni con forzature:

    // 3.B.2.1
    
    var number = 1,
      string = "1",
      bool = false;
    
    number;
    // 1
    
    number + "";
    // "1"
    
    string;
    // "1"
    
    +string;
    // 1
    
    +string++;
    // 1
    
    string;
    // 2
    
    bool;
    // false
    
    +bool;
    // 0
    
    bool + "";
    // "false"
    // 3.B.2.2
    
    var number = 1,
      string = "1",
      bool = true;
    
    string === number;
    // false
    
    string === number + "";
    // true
    
    +string === number;
    // true
    
    bool === number;
    // false
    
    +bool === number;
    // true
    
    bool === string;
    // false
    
    bool === !!string;
    // true
    // 3.B.2.3
    
    var array = [ "a", "b", "c" ];
    
    !!~array.indexOf("a");
    // true
    
    !!~array.indexOf("b");
    // true
    
    !!~array.indexOf("c");
    // true
    
    !!~array.indexOf("d");
    // false
    
    // Notate che i summenzionati dovrebbero essere considerati "inutilmente chiari"
    // &Egrave; da preferire il più ovvio approccio di comparazione del valore ritornato
    // da indexOf, cioè:
    
    if ( array.indexOf( "a" ) >= 0 ) {
      // ...
    }
    // 3.B.2.3
    
    
    var num = 2.5;
    
    parseInt( num, 10 );
    
    // è l'equivalente di...
    
    ~~num;
    
    num >> 0;
    
    num >>> 0;
    
    // Tutti danno risultato di 2
    
    
    // Comunque ricordate che i numeri negativi verranno trattati differentemente...
    
    var neg = -2.5;
    
    parseInt( neg, 10 );
    
    // è l'equivalente di...
    
    ~~neg;
    
    neg >> 0;
    
    // Tutti danno risultato di -2
    // Sebbene...
    
    neg >>> 0
    
    // Darà come risultato 4294967294
    
    
    
    
  4. Valutazione condizionale

    // 4.1.1
    // Quando si deve solo valutare che un array abbia elementi,
    // invece di questo:
    if ( array.length > 0 ) ...
    
    // ...valutatene lo stato di verità, in questo modo:
    if ( array.length ) ...
    
    
    // 4.1.2
    // Quando si deve solo valutare che un array è vuoto,
    // invece di questo:
    if ( array.length === 0 ) ...
    
    // ...valutatene lo stato di verità, in questo modo:
    if ( !array.length ) ...
    
    
    // 4.1.3
    // Quando si deve solo valutare che una stringa non è vuota,
    // invece di questo:
    if ( string !== "" ) ...
    
    // ...valutatene lo stato di verità, in questo modo:
    if ( string ) ...
    
    
    // 4.1.4
    // Quando si deve solo valutare che una stringa _è_ vuota,
    // invece di questo:
    if ( string === "" ) ...
    
    // ...valutatene lo stato di verità, in questo modo:
    if ( !string ) ...
    
    
    // 4.1.5
    // Quando si deve solo valutare che un riferimento è vero,
    // invece di questo:
    if ( foo === true ) ...
    
    // ...valutatelo per il suo significato, avvantaggiatevi con le funzionalità proprie del linguaggio:
    if ( foo ) ...
    
    
    // 4.1.6
    // Quando si deve solo valutare che un riferimento è falso,
    // invece di questo:
    if ( foo === false ) ...
    
    // ...usate la negazione per forzare una valutazione vera
    if ( !foo ) ...
    
    // ...ma state attenti, questo varrà anche per: 0, "", null, undefined, NaN
    // Se _DOVETE_ testare per un falso booleano, allora usate
    if ( foo === false ) ...
    
    
    // 4.1.7
    // Quando si deve solo testare che un riferimento potrebbe essere null o undefined,
    // ma NON falso, "" o 0, invece di questo:
    if ( foo === null || foo === undefined ) ...
    
    // ...avvantaggiatevi della forzatura di tipo fatta da ==, in questo modo:
    if ( foo == null ) ...
    
    // Ricordate, l'uso di == farà corrispondere un `null` SIA a `null` che a `undefined`
    // ma non a `false`, "" o 0
    null == undefined
    

    Valutate SEMPRE per il risultato migliore e più accurato - quella sopra è una linea guida, non un dogma.

    // 4.2.1
    // Forzatura di tipo e note di valutazione
    
    // Preferite `===` a `==` (a meno che il caso non richieda una valutazione non tipizzata)
    
    // === non forza il tipo, ciò significa che:
    
    "1" === 1:
    // false
    
    // == forza il tipo, ciò significa che:
    
    "1" == 1;
    // true
    
    
    // 4.2.2
    // Booleani, verità e falsità
    
    // Booleani:
    true, false
    
    // Verità:
    "foo", 1
    
    // Falsità:
    "", 0, null, undefined, NaN, void 0
    
  5. Stile pratico

    // 5.1.1
    // Un modulo pratico
    
    (function( global ) {
      var Module = (function() {
    
        var data = "secret";
    
        return {
          // Qualche proprietà booleana
          bool: true,
          // Un valore stringa
          string: "a string",
          // Una proprietà array
          array: [ 1, 2, 3, 4 ],
          // Una proprietà oggetto
          object: {
            lang: "en-US"
          },
          getData: function() {
            // ottiene il valore corrente di `data`
            return data;
          },
          setData: function( value ) {
            // imposta il valore di `data` e lo ritorna
            return ( data = value );
          }
        };
      })();
    
      // Altre cose posso accadere qui
    
      // esponiamo il nostro modulo all'oggetto globale
      global.Module = Module;
    
    })( this );
    // 5.2.1
    // Un costruttore pratico
    
    (function( global ) ) {
    
      function Ctor( foo ) {
    
        this.foo = foo;
    
        return this;
      }
    
      Ctor.prototype.getFoo = function() {
        return this.foo;
      };
    
      Ctor.prototype.setFoo = function( val ) {
        return ( this.foo = val );
      };
    
    
      // Per richiamare il costruttore senza `new`, potreste fare così:
      var ctor = function( foo ) {
        return new Ctor( foo );
      };
    
    
      // esponiamo il nostro costruttore all'oggetto globale
      global.ctor = ctor;
    
    })( this );
  6. Nomenclatura

    Voi non siete dei compilatori/compressori umani di codice, perciò non provate ad esserlo.

    Il seguente codice è un esempio di tremenda nomenclatura:

    // 6.1.1
    // Esempio di codice con nomi per niente chiari
    
    function q(s) {
      return document.querySelectorAll(s);
    }
    var i,a=[],els=q("#foo");
    for(i=0;i<els.length;i++){a.push(els[i]);}

    Sicuramente avrete scritto codice come questo - con la speranza che ciò termini oggi.

    Ecco lo stesso pezzo di codice, ma con una nomencaltura più riflessiva ed esplicativa (ed una struttura leggibile):

    // 6.2.1
    // Esempio di codice con nomi migliorati
    
    function query( selector ) {
      return document.querySelectorAll( selector );
    }
    
    var idx = 0,
      elements = [],
      matches = query("#foo"),
      length = matches.length;
    
    for( ; idx < length; idx++ ){
      elements.push( matches[ idx ] );
    }

    Alcune ulteriori considerazioni:

    // 6.3.1
    // Nominare stringhe
    
    `dog` è una stringa
    
    
    // 6.3.2
    // Nominare array
    
    `dogs` è un array di stringhe `dog`
    
    
    // 6.3.3
    // Nominare funzioni, oggetti, istanze, ecc.
    
    camelCase; dichiarazioni di funzione e variabile
    
    // 6.3.4
    // Nominare costruttori, prototipi, ecc.
    
    PascalCase; funzione costruttore
    
    
    // 6.3.5
    // Nominare espressioni regolari
    
    rDesc = //;
    
    
    // 6.3.6
    // Dalla guida allo stile della libreria di Google Closure
    
    functionNamesLikeThis;
    variableNamesLikeThis;
    ConstructorNamesLikeThis;
    EnumNamesLikeThis;
    methodNamesLikeThis;
    SYMBOLIC_CONSTANTS_LIKE_THIS;
    
    
    
  7. Varie

    Questa sezione servirà ad illustrare idee e concetti che non dovrebbero essere considerati un dogma, ma che invece esistono per incoraggiare pratiche di analisi nel tentativo di ricercare le migliori modalità per fare lavori di programmazione JavaScript comuni.

    A. L'utilizzo di switch dovrebbe essere evitato, il metodo moderno di analisi metterà nella lista nera le funzioni con istruzioni switch

    Sembra che ci sia un drastico miglioramento nell'esecuzione di istruzioni switch nelle ultime release di Firefox e Chrome. http://jsperf.com/switch-vs-object-literal-vs-module

    Visibili miglioramenti vengono riportati anche qui: https://github.com/rwldrn/idiomatic.js/issues/13

    // 7.A.1.1
    // Un esempio di istruzione switch
    
    switch( foo ) {
      case "alpha":
        alpha();
        break;
      case "beta":
        beta();
        break;
      default:
        // qualcosa da eseguire di default
        break;
    }
    
    // 7.A.1.2
    // Un migliore approccio sarebbe quello di usare un oggetto o anche un modulo:
    
    var switchObj = {
      alpha: function() {
        // istruzioni
        // termina e ritorna
      },
      beta: function() {
        // istruzioni
        // termina e ritorna       
      },
      _default: function() {
        // istruzioni
        // termina e ritorna     
      }
    };
    
    var switchModule = (function () {
      return {
        alpha: function() {
          // istruzioni
          // termina e ritorna
        },
        beta: function() {
          // istruzioni
          // termina e ritorna       
        },
        _default: function() {
          // istruzioni
          // termina e ritorna     
        }
      };
    })();
    
    
    // 7.A.1.3
    // Se `foo` è una proprietà di `switchObj` o `switchModule`, lo si esegue come un metodo...
    
    ( Object.hasOwnProperty.call( switchObj, foo ) && switchObj[ foo ] || switchObj._default )( args );
    
    ( Object.hasOwnProperty.call( switchObj, foo ) && switchModule[ foo ] || switchModule._default )( args );
    
    // Se conoscete e vi fidate del valore di `foo`, potete anche omettere il controllo OR
    // lasciando solo l'esecuzione:
    
    switchObj[ foo ]( args );
    
    switchModule[ foo ]( args );
    
    
    // Questo pattern promuove anche la riusabilità del codice.
    

    B. I ritorni da funzione anticipati promuovono la leggibilità del codice a fronte di una differenza di performance trascurabile

    // 7.B.1.1
    // Sbagliato:
    function returnLate( foo ) {
      var ret;
    
      if ( foo ) {
        ret = "foo";
      } else {
        ret = "quux";
      }
      return ret;
    }
    
    // Corretto:
    
    function returnEarly( foo ) {
    
      if ( foo ) {
        return "foo";
      }
      return "quux";
    }
    
  8. Oggetti nativi e ospite

    Il principio base è:

    Non fare cose stupide e tutto andrà per il meglio.

    Per rafforzare questo concetto, date un'occhiata alla seguente presentazione:

    “Everything is Permitted: Extending Built-ins” di Andrew Dupont (JSConf2011, Portland, Oregon)

    http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitted-extending-built-ins-5211542

  9. Commenti

    • Linea singola sopra il codice a cui ci si riferisce
    • Multilinea va bene
    • Commenti a fine linea sono proibiti!
    • Lo stile JSDoc va bene, ma richiede un significante investimento di tempo
  10. Un codice di linguaggio

    I programmi dovrebbero essere scritti in un linguaggio, qualsiasi esso sia, come richiesto dal mantenitore o dai mantenitori.

Appendice

Comma First.

Qualsiasi progetto che citi questo documento come sua guida base di stile non accetterà la formattazione comma first del codice, a meno che non sia esplicitamente specificato dall'autore del progetto.

Something went wrong with that request. Please try again.