Skip to content

Latest commit

 

History

History
1398 lines (986 loc) · 33.6 KB

RULES-iteu.md

File metadata and controls

1398 lines (986 loc) · 33.6 KB

JavaScript Standard Style

EnglishEspañol (Latinoamérica)FrançaisItaliano (Italian)한국어 (Korean)Português (Brasil)简体中文 (Simplified Chinese)繁體中文 (Taiwanese Mandarin)

js-standard-style

Questo è un TL;DR (troppo lungo, non ho letto) delle regole JavaScript di standard.

Il modo migliore per imparare standard è quello di installarlo e provarlo sul tuo codice.

Regole

  • Usa due spazi per indentare.

    eslint: indent

    function hello (name) {
      console.log('hi', name)
    }
  • Usa il singolo apostrofo per le stringhe tranne per evitare l'escaping.

    eslint: quotes

    console.log('hello there')
    $("<div class='box'>")
  • Niente variabili inutilizzate.

    eslint: no-unused-vars

    function myFunction () {
      var result = something()   // ✗ evita
    }
  • Aggiungi uno spazio dopo le parole chiave.

    eslint: keyword-spacing

    if (condition) { ... }   // ✓ ok
    if(condition) { ... }    // ✗ evita
  • Aggiungi uno spazio prima delle parenti di una dichiarazione di una funzione.

    eslint: space-before-function-paren

    function name (arg) { ... }   // ✓ ok
    function name(arg) { ... }    // ✗ evita
    
    run(function () { ... })      // ✓ ok
    run(function() { ... })       // ✗ evita
  • Usa sempree === invece di ==.
    Eccezione: obj == null è consentito per controllare null || undefined.

    eslint: eqeqeq

    if (name === 'John')   // ✓ ok
    if (name == 'John')    // ✗ evita
    if (name !== 'John')   // ✓ ok
    if (name != 'John')    // ✗ evita
  • Operatori infisso necessitano sempre di uno spazio.

    eslint: space-infix-ops

    // ✓ ok
    var x = 2
    var message = 'hello, ' + name + '!'
    // ✗ evita
    var x=2
    var message = 'hello, '+name+'!'
  • Le virgole devono avere uno spazio dopo di loro.

    eslint: comma-spacing

    // ✓ ok
    var list = [1, 2, 3, 4]
    function greet (name, options) { ... }
    // ✗ evita
    var list = [1,2,3,4]
    function greet (name,options) { ... }
  • Tieni gli else sulla stessa linea della parentesi graffa.

    eslint: brace-style

    // ✓ ok
    if (condition) {
      // ...
    } else {
      // ...
    }
    // ✗ evita
    if (condition) {
      // ...
    }
    else {
      // ...
    }
  • Per dichiarazioni if su più righe, utilizza le parentesi graffe.

    eslint: curly

    // ✓ ok
    if (options.quiet !== true) console.log('done')
    // ✓ ok
    if (options.quiet !== true) {
      console.log('done')
    }
    // ✗ evita
    if (options.quiet !== true)
      console.log('done')
  • Gestisci sempre l'oggetto err come parametro di funzione.

    eslint: handle-callback-err

    // ✓ ok
    run(function (err) {
      if (err) throw err
      window.alert('done')
    })
    // ✗ evita
    run(function (err) {
      window.alert('done')
    })
  • Usa il prefisso per le variabili gloabli con window..
    Eccezioni sono: document, console e navigator.

    eslint: no-undef

    window.alert('hi')   // ✓ ok
  • Non sono consentite più di una riga vuota.

    eslint: no-multiple-empty-lines

    // ✓ ok
    var value = 'hello world'
    console.log(value)
    // ✗ evita
    var value = 'hello world'
    
    
    console.log(value)
  • Per l'operatore ternario su più di una riga, piazza ? e : nelle righe che gli appartengono.

    eslint: operator-linebreak

    // ✓ ok
    var location = env.development ? 'localhost' : 'www.api.com'
    
    // ✓ ok
    var location = env.development
      ? 'localhost'
      : 'www.api.com'
    
    // ✗ evita
    var location = env.development ?
      'localhost' :
      'www.api.com'
  • Per l'utilizzo del var, ogni assegnazione deve avere la sua definizione

    eslint: one-var

    // ✓ ok
    var silent = true
    var verbose = true
    
    // ✗ evita
    var silent = true, verbose = true
    
    // ✗ evita
    var silent = true,
        verbose = true
  • Circonda gli assegnatori condizionali con parentesi aggiuntive. Questo assicura che ci sia l'espressione è intenzionalmente un assegnamento (=) invece di un errore di scrittura (===).

    eslint: no-cond-assign

    // ✓ ok
    while ((m = text.match(expr))) {
      // ...
    }
    
    // ✗ evita
    while (m = text.match(expr)) {
      // ...
    }
  • Aggiungi degli spazie all'interno di blocchi su una singola riga.

    eslint: block-spacing

      function foo () {return true}    // ✗ evita
      function foo () { return true }  // ✓ ok
  • Utilizza il camelcase per i nomi delle variabili e funzioni.

    eslint: camelcase

      function my_function () { }    // ✗ evita
      function myFunction () { }     // ✓ ok
    
      var my_var = 'hello'           // ✗ evita
      var myVar = 'hello'            // ✓ ok
  • I trailing comma non sono ammessi.

    eslint: comma-dangle

      var obj = {
        message: 'hello',   // ✗ evita
      }
  • The virgole devono essere messe alla fine della riga corrente

    eslint: comma-style

      var obj = {
        foo: 'foo'
        ,bar: 'bar'   // ✗ avoid
      }
    
      var obj = {
        foo: 'foo',
        bar: 'bar'   // ✓ ok
      }
  • Il punto deve essere sulla stessa linea della proprietà.

    eslint: dot-location

      console.
        log('hello')  // ✗ avoid
    
      console
        .log('hello') // ✓ ok
  • I file devono terminare con una nuova linea.

    eslint: eol-last

  • No spazi tra la definizione di una funzione e la sua invocazione

    eslint: func-call-spacing

    console.log ('hello') // ✗ avoid
    console.log('hello')  // ✓ ok
  • Aggiungi uno spazio tra i due punti e il valore della chiave all'interno di un oggetto.

    eslint: key-spacing

    var obj = { 'key' : 'value' }    // ✗ avoid
    var obj = { 'key' :'value' }     // ✗ avoid
    var obj = { 'key':'value' }      // ✗ avoid
    var obj = { 'key': 'value' }     // ✓ ok
  • I nomi dei costruttori devono iniziare con la lettera maiuscola

    eslint: new-cap

    function animal () {}
    var dog = new animal()    // ✗ avoid
    
    function Animal () {}
    var dog = new Animal()    // ✓ ok
  • I costruttori senza argomenti devono essere invocati con le parentesi.

    eslint: new-parens

    function Animal () {}
    var dog = new Animal    // ✗ avoid
    var dog = new Animal()  // ✓ ok
  • Gli oggetti devono un getter quando un settere viene definito.

    eslint: accessor-pairs

    var person = {
      set name (value) {    // ✗ avoid
        this._name = value
      }
    }
    
    var person = {
      set name (value) {
        this._name = value
      },
      get name () {         // ✓ ok
        return this._name
      }
    }
  • I costruttori di classi derivate devono chiamare super.

    eslint: constructor-super

    class Dog {
      constructor () {
        super()   // ✗ avoid
      }
    }
    
    class Dog extends Mammal {
      constructor () {
        super()   // ✓ ok
      }
    }
  • Usa gli array literals invece dei costruttori.

    eslint: no-array-constructor

    var nums = new Array(1, 2, 3)   // ✗ avoid
    var nums = [1, 2, 3]            // ✓ ok
  • Evita l'utilizzo di arguments.callee e arguments.caller.

    eslint: no-caller

    function foo (n) {
      if (n <= 0) return
    
      arguments.callee(n - 1)   // ✗ avoid
    }
    
    function foo (n) {
      if (n <= 0) return
    
      foo(n - 1)
    }
  • Non è possibile cambiare il nome delle classi.

    eslint: no-class-assign

    class Dog {}
    Dog = 'Fido'    // ✗ avoid
  • Evita di modificare il varole di una variabile dichiarata usando const.

    eslint: no-const-assign

    const score = 100
    score = 125       // ✗ avoid
  • Evita l'uso delle espressioni costanti all'interno delle condizioni (eccezione fatta per i cicli).

    eslint: no-constant-condition

    if (false) {    // ✗ avoid
      // ...
    }
    
    if (x === 0) {  // ✓ ok
      // ...
    }
    
    while (true) {  // ✓ ok
      // ...
    }
  • No controllo dei caratteri nelle espressioni regolari.

    eslint: no-control-regex

    var pattern = /\x1f/    // ✗ avoid
    var pattern = /\x20/    // ✓ ok
  • No debugger nel codice.

    eslint: no-debugger

    function sum (a, b) {
      debugger      // ✗ avoid
      return a + b
    }
  • Non usare delete sulle variabili.

    eslint: no-delete-var

    var name
    delete name     // ✗ avoid
  • No argomenti doppi all'interno della definizione di una funzione.

    eslint: no-dupe-args

    function sum (a, b, a) {  // ✗ avoid
      // ...
    }
    
    function sum (a, b, c) {  // ✓ ok
      // ...
    }
  • No nomi doppi all'interno di una classe.

    eslint: no-dupe-class-members

    class Dog {
      bark () {}
      bark () {}    // ✗ avoid
    }
  • Non è possibile dichiarare chiavi doppie degli oggetti literals.

    eslint: no-dupe-keys

    var user = {
      name: 'Jane Doe',
      name: 'John Doe'    // ✗ avoid
    }
  • Non è possibile dichiarare due case che controllano lo stesso valore all'interno di uno switch

    eslint: no-duplicate-case

    switch (id) {
      case 1:
        // ...
      case 1:     // ✗ avoid
    }
  • Utilizza un solo import per module.

    eslint: no-duplicate-imports

    import { myFunc1 } from 'module'
    import { myFunc2 } from 'module'          // ✗ avoid
    
    import { myFunc1, myFunc2 } from 'module' // ✓ ok
  • No caratteri vuoti all'iterno delle espressioni regolari.

    eslint: no-empty-character-class

    const myRegex = /^abc[]/      // ✗ avoid
    const myRegex = /^abc[a-z]/   // ✓ ok
  • Non è possibile usare il destructuring vuoto

    eslint: no-empty-pattern

    const { a: {} } = foo         // ✗ avoid
    const { a: { b } } = foo      // ✓ ok
  • No all'uso di eval().

    eslint: no-eval

    eval( "var result = user." + propName ) // ✗ avoid
    var result = user[propName]             // ✓ ok
  • No all reassegnamento delle eccezioni all'interno di blocchi catch.

    eslint: no-ex-assign

    try {
      // ...
    } catch (e) {
      e = 'new value'             // ✗ avoid
    }
    
    try {
      // ...
    } catch (e) {
      const newVal = 'new value'  // ✓ ok
    }
  • Non è possibile estendere oggetti nativi.

    eslint: no-extend-native

    Object.prototype.age = 21     // ✗ avoid
  • Evita il binding non necessari.

    eslint: no-extra-bind

    const name = function () {
      getName()
    }.bind(user)    // ✗ avoid
    
    const name = function () {
      this.getName()
    }.bind(user)    // ✓ ok
  • Evita di effettuare il cast di booleani che non sono necessari.

    eslint: no-extra-boolean-cast

    const result = true
    if (!!result) {   // ✗ avoid
      // ...
    }
    
    const result = true
    if (result) {     // ✓ ok
      // ...
    }
  • No parentesi non necessarie intorno alle funzioni.

    eslint: no-extra-parens

    const myFunc = (function () { })   // ✗ avoid
    const myFunc = function () { }     // ✓ ok
  • Utilizza il break per evitare l'esecuzioni dei successivi case all'interno di un blocco switch.

    eslint: no-fallthrough

    switch (filter) {
      case 1:
        doSomething()    // ✗ avoid
      case 2:
        doSomethingElse()
    }
    
    switch (filter) {
      case 1:
        doSomething()
        break           // ✓ ok
      case 2:
        doSomethingElse()
    }
    
    switch (filter) {
      case 1:
        doSomething()
        // fallthrough  // ✓ ok
      case 2:
        doSomethingElse()
    }
  • No ai decimali con la virgola mobile.

    eslint: no-floating-decimal

    const discount = .5      // ✗ avoid
    const discount = 0.5     // ✓ ok
  • Evita la riassegnazione di una funzione dichiarata.

    eslint: no-func-assign

    function myFunc () { }
    myFunc = myOtherFunc    // ✗ avoid
  • Evita la riassegnazione di oggetti che possono essere solo letti.

    eslint: no-global-assign

    window = {}     // ✗ avoid
  • No agli eval() sottointesi.

    eslint: no-implied-eval

    setTimeout("alert('Hello world')")                   // ✗ avoid
    setTimeout(function () { alert('Hello world') })     // ✓ ok
  • No alla dichiarazione di funzioni all'interno di blocchi innestati.

    eslint: no-inner-declarations

    if (authenticated) {
      function setAuthUser () {}    // ✗ avoid
    }
  • No a stringhe di expressioni regolari invalide all'interno dei costruttori RegExp.

    eslint: no-invalid-regexp

    RegExp('[a-z')    // ✗ avoid
    RegExp('[a-z]')   // ✓ ok
  • No a spazi irregolari.

    eslint: no-irregular-whitespace

    function myFunc () /*<NBSP>*/{}   // ✗ avoid
  • No all'uso di __iterator__.

    eslint: no-iterator

    Foo.prototype.__iterator__ = function () {}   // ✗ avoid
  • No a etichette che condividono lo stesso nome di una variabile all'interno dello stesso scope.

    eslint: no-label-var

    var score = 100
    function game () {
      score: while (true) {      // ✗ avoid
        score -= 10
        if (score > 0) continue score
        break
      }
    }
  • No al blocco label.

    eslint: no-labels

    label:
      while (true) {
        break label     // ✗ avoid
      }
  • No a blocchi non necessari.

    eslint: no-lone-blocks

    function myFunc () {
      {                   // ✗ avoid
        myOtherFunc()
      }
    }
    
    function myFunc () {
      myOtherFunc()       // ✓ ok
    }
  • Evita di mixare spazi e tab per indentare.

    eslint: no-mixed-spaces-and-tabs

  • Non usare spazi multipli per indentare.

    eslint: no-multi-spaces

    const id =    1234    // ✗ avoid
    const id = 1234       // ✓ ok
  • No a stringhe su più linee.

    eslint: no-multi-str

    const message = 'Hello \
                     world'     // ✗ avoid
  • No all'uso del new senza l'assegnazione ad una variabile.

    eslint: no-new

    new Character()                     // ✗ avoid
    const character = new Character()   // ✓ ok
  • No all'uso del costruttore Function.

    eslint: no-new-func

    var sum = new Function('a', 'b', 'return a + b')    // ✗ avoid
  • No all'uso del costruttore Object.

    eslint: no-new-object

    let config = new Object()   // ✗ avoid
  • No all'uso di new require.

    eslint: no-new-require

    const myModule = new require('my-module')    // ✗ avoid
  • No all'uso del costruttore Symbol.

    eslint: no-new-symbol

    const foo = new Symbol('foo')   // ✗ avoid
  • No all'uso di istanze di primitive.

    eslint: no-new-wrappers

    const message = new String('hello')   // ✗ avoid
  • Non chiamare le proprietà di oggetti globali come funzioni.

    eslint: no-obj-calls

    const math = Math()   // ✗ avoid
  • No agli ottali literals.

    eslint: no-octal

    const num = 042     // ✗ avoid
    const num = '042'   // ✓ ok
  • No all'escape di sequenze di ottali nelle stringhe letterali.

    eslint: no-octal-escape

    const copyright = 'Copyright \251'  // ✗ avoid
  • Evita la concatenazione di strighe quando si usano __dirname e __filename.

    eslint: no-path-concat

    const pathToFile = __dirname + '/app.js'            // ✗ avoid
    const pathToFile = path.join(__dirname, 'app.js')   // ✓ ok
  • Evita l'uso di __proto__. Usa invece getPrototypeOf.

    eslint: no-proto

    const foo = obj.__proto__               // ✗ avoid
    const foo = Object.getPrototypeOf(obj)  // ✓ ok
  • No alla ridichiarazione di variabili.

    eslint: no-redeclare

    let name = 'John'
    let name = 'Jane'     // ✗ avoid
    
    let name = 'John'
    name = 'Jane'         // ✓ ok
  • Evita spazi multipli all'interno di espressioni regolari literals.

    eslint: no-regex-spaces

    const regexp = /test   value/   // ✗ avoid
    
    const regexp = /test {3}value/  // ✓ ok
    const regexp = /test value/     // ✓ ok
  • Gli assegnamenti nei blocchi return devono essere circondati da parentesi .

    eslint: no-return-assign

    function sum (a, b) {
      return result = a + b     // ✗ avoid
    }
    
    function sum (a, b) {
      return (result = a + b)   // ✓ ok
    }
  • Evita di assegnare una variabile a se stessa

    eslint: no-self-assign

    name = name   // ✗ avoid
  • Evita di confrontare una variabile con se stessa.

    eslint: no-self-compare

    if (score === score) {}   // ✗ avoid
  • Evita l'uso della virgola come operatore.

    eslint: no-sequences

    if (doSomething(), !!test) {}   // ✗ avoid
  • Nomi protetti non possono essere reassegnati (shadowing).

    eslint: no-shadow-restricted-names

    let undefined = 'value'     // ✗ avoid
  • Array sparsi non sono consentiti.

    eslint: no-sparse-arrays

    let fruits = ['apple',, 'orange']       // ✗ avoid
  • I tab non dovrebbero essere utilizzati

    eslint: no-tabs

  • Strighe regolari non devono contenere i placeholders propri dei template literal.

    eslint: no-template-curly-in-string

    const message = 'Hello ${name}'   // ✗ avoid
    const message = `Hello ${name}`   // ✓ ok
  • super() deve essere chiamato prima di this.

    eslint: no-this-before-super

    class Dog extends Animal {
      constructor () {
        this.legs = 4     // ✗ avoid
        super()
      }
    }
  • Puoi usare throw solo su un oggetto Error.

    eslint: no-throw-literal

    throw 'error'               // ✗ avoid
    throw new Error('error')    // ✓ ok
  • Spazi bianchi banditi alla fine di una linea.

    eslint: no-trailing-spaces

  • Inizializzare con undefined non è consentito.

    eslint: no-undef-init

    let name = undefined    // ✗ avoid
    
    let name
    name = 'value'          // ✓ ok
  • No alla non-modifica delle condizioni all'interno dei cicli.

    eslint: no-unmodified-loop-condition

    for (let i = 0; i < items.length; j++) {...}    // ✗ avoid
    for (let i = 0; i < items.length; i++) {...}    // ✓ ok
  • No all'uso dell'operatore ternario quando esiste una alternativa migliore.

    eslint: no-unneeded-ternary

    let score = val ? val : 0     // ✗ avoid
    let score = val || 0          // ✓ ok
  • No a codice non eseguibile dopo l'uso di return, throw, continue, e break.

    eslint: no-unreachable

    function doSomething () {
      return true
      console.log('never called')     // ✗ avoid
    }
  • No a controlli di flusso all'interno di blocchi finally.

    eslint: no-unsafe-finally

    try {
      // ...
    } catch (e) {
      // ...
    } finally {
      return 42     // ✗ avoid
    }
  • L'operando sinistro di una operazione relazionale non può essere negato.

    eslint: no-unsafe-negation

    if (!key in obj) {}       // ✗ avoid
  • Evita l'uso non necessario di .call() e .apply().

    eslint: no-useless-call

    sum.call(null, 1, 2, 3)   // ✗ avoid
  • Evita l'uso di una non necessario computed property all'interno di una chiave di un oggetto

    eslint: no-useless-computed-key

    const user = { ['name']: 'John Doe' }   // ✗ avoid
    const user = { name: 'John Doe' }       // ✓ ok
  • No all'uso non necessario di costruttori.

    eslint: no-useless-constructor

    class Car {
      constructor () {      // ✗ avoid
      }
    }
  • No all'uso non necessario degli escape.

    eslint: no-useless-escape

    let message = 'Hell\o'  // ✗ avoid
  • Rinominare l'assegnamento di import, export, e destrutturazione (destructuring) usano lo stesso nome non è consentito.

    eslint: no-useless-rename

    import { config as config } from './config'     // ✗ avoid
    import { config } from './config'               // ✓ ok
  • No spazi prima di una proprietà

    eslint: no-whitespace-before-property

    user .name      // ✗ avoid
    user.name       // ✓ ok
  • No all'uso di with.

    eslint: no-with

    with (val) {...}    // ✗ avoid
  • Mantere consistenza di nuove righe all'interno delle proprietà di un oggetto.

    eslint: object-property-newline

    const user = {
      name: 'Jane Doe', age: 30,
      username: 'jdoe86'            // ✗ avoid
    }
    
    const user = { name: 'Jane Doe', age: 30, username: 'jdoe86' }    // ✓ ok
    
    const user = {
      name: 'Jane Doe',
      age: 30,
      username: 'jdoe86'
    }                                                                 // ✓ ok
  • No padding all'interno dei blocchi.

    eslint: padded-blocks

    if (user) {
                                // ✗ avoid
      const name = getName()
    
    }
    
    if (user) {
      const name = getName()    // ✓ ok
    }
  • No spazi tra l'operatore spread e la loro espressione.

    eslint: rest-spread-spacing

    fn(... args)    // ✗ avoid
    fn(...args)     // ✓ ok
  • Le virgole devono avere uno spazio dopo e non prima.

    eslint: semi-spacing

    for (let i = 0 ;i < items.length ;i++) {...}    // ✗ avoid
    for (let i = 0; i < items.length; i++) {...}    // ✓ ok
  • Avere uno spazio prima dei blocchi.

    eslint: space-before-blocks

    if (admin){...}     // ✗ avoid
    if (admin) {...}    // ✓ ok
  • No spazi all'interno delle parentesi

    eslint: space-in-parens

    getName( name )     // ✗ avoid
    getName(name)       // ✓ ok
  • Uso dello spazio dopo l'uso di un operatore unario.

    eslint: space-unary-ops

    typeof!admin        // ✗ avoid
    typeof !admin        // ✓ ok
  • Usa gli spazi dentro i commenti.

    eslint: spaced-comment

    //comment           // ✗ avoid
    // comment          // ✓ ok
    
    /*comment*/         // ✗ avoid
    /* comment */       // ✓ ok
  • No spazi dentro le strighe template.

    eslint: template-curly-spacing

    const message = `Hello, ${ name }`    // ✗ avoid
    const message = `Hello, ${name}`      // ✓ ok
  • Usa IsNaN() quando controlli NaN.

    eslint: use-isnan

    if (price === NaN) { }      // ✗ avoid
    if (isNaN(price)) { }       // ✓ ok
  • typeof deve essere comparato con una stringa valida.

    eslint: valid-typeof

    typeof name === 'undefimed'     // ✗ avoid
    typeof name === 'undefined'     // ✓ ok
  • Espressioni di funzioni immediatamente invocate (IIFEs - Immediately Invoked Function Expressions) devono essere circondate da parentesi.

    eslint: wrap-iife

    const getName = function () { }()     // ✗ avoid
    
    const getName = (function () { }())   // ✓ ok
    const getName = (function () { })()   // ✓ ok
  • Mettere uno spazio prima e dopo * dentro le espressioni yield* .

    eslint: yield-star-spacing

    yield* increment()    // ✗ avoid
    yield * increment()   // ✓ ok
  • Evitare condizioni Yoda.

    eslint: yoda

    if (42 === age) { }    // ✗ avoid
    if (age === 42) { }    // ✓ ok

Semicolons

  • No punti e virgola (semicolons). (see: 1, 2, 3)

    eslint: semi

    window.alert('hi')   // ✓ ok
    window.alert('hi');  // ✗ avoid
  • Mai iniziare una linea con (, [, o `. Questo è l'unico trucchetto che permette di omettere i punti e virgola. E standard ti protegge da potenziali errori.

    eslint: no-unexpected-multiline

    // ✓ ok
    ;(function () {
      window.alert('ok')
    }())
    
    // ✗ avoid
    (function () {
      window.alert('ok')
    }())
    // ✓ ok
    ;[1, 2, 3].forEach(bar)
    
    // ✗ avoid
    [1, 2, 3].forEach(bar)
    // ✓ ok
    ;`hello`.indexOf('o')
    
    // ✗ avoid
    `hello`.indexOf('o')

    Nota: Se tendi a scrivere codice in questo modo, probabilmente stai cercando di essere troppo furbo.

    È scoraggiato l'uso di scorciatoie, in favore di espressioni chiare e leggibili quando possibile.

    Invece di:

    ;[1, 2, 3].forEach(bar)

    È preferito questo approccio:

    var nums = [1, 2, 3]
    nums.forEach(bar)

Letture utili

E un video utile:

Oggigiorno, tutti i più popolari minificatori di codice si basano su AST, quindi gestiscono il JavaScript senza punti e virgola (semicolons-less) senza problemi (visto che i punti e virgola non sono obbligatori in JavaScript).

[Relying on automatic semicolon insertion] is quite safe, and perfectly valid JS that every browser understands. Closure compiler, yuicompressor, packer, and jsmin all can properly minify it. There is no performance impact anywhere.

I am sorry that, instead of educating you, the leaders in this language community have given you lies and fear. That was shameful. I recommend learning how statements in JS are actually terminated (and in which cases they are not terminated), so that you can write code that you find beautiful.

In general, \n ends a statement unless:

  1. The statement has an unclosed paren, array literal, or object literal or ends in some other way that is not a valid way to end a statement. (For instance, ending with . or ,.)
  2. The line is -- or ++ (in which case it will decrement/increment the next token.)
  3. It is a for(), while(), do, if(), or else, and there is no {
  4. The next line starts with [, (, +, *, /, -, ,, ., or some other binary operator that can only be found between two tokens in a single expression.

The first is pretty obvious. Even JSLint is ok with \n chars in JSON and parenthesized constructs, and with var statements that span multiple lines ending in ,.

The second is super weird. I’ve never seen a case (outside of these sorts of conversations) where you’d want to do write i\n++\nj, but, point of fact, that’s parsed as i; ++j, not i++; j.

The third is well understood, if generally despised. if (x)\ny() is equivalent to if (x) { y() }. The construct doesn’t end until it reaches either a block, or a statement.

; is a valid JavaScript statement, so if(x); is equivalent to if(x){} or, “If x, do nothing.” This is more commonly applied to loops where the loop check also is the update function. Unusual, but not unheard of.

The fourth is generally the fud-inducing “oh noes, you need semicolons!” case. But, as it turns out, it’s quite easy to prefix those lines with semicolons if you don’t mean them to be continuations of the previous line. For example, instead of this:

foo();
[1,2,3].forEach(bar);

you could do this:

foo()
;[1,2,3].forEach(bar)

The advantage is that the prefixes are easier to notice, once you are accustomed to never seeing lines starting with ( or [ without semis.