JavaScript Standard Style
English • Español (Latinoamérica) • Français • Bahasa Indonesia • Italiano (Italian) • 日本語 (Japanese) • 한국어 (Korean) • Português (Brasil) • 简体中文 (Simplified Chinese) • 繁體中文 (Taiwanese Mandarin)
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 controllarenull || 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
enavigator
.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`](http://eslint.org/docs/rules/operator-linebreak)
```js
// ✓ 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
earguments.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 unoswitch
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 successivicase
all'interno di un bloccoswitch
.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 octal = 042 // ✗ avoid const decimal = 34 // ✓ ok const octalString = '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 invecegetPrototypeOf
.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 dithis
.eslint:
no-this-before-super
class Dog extends Animal { constructor () { this.legs = 4 // ✗ avoid super() } }
-
Puoi usare
throw
solo su un oggettoError
.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
, ebreak
.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 controlliNaN
.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 espressioniyield*
.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. Estandard
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
- An Open Letter to JavaScript Leaders Regarding Semicolons
- JavaScript Semicolon Insertion – Everything you need to know
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 afor()
,while()
,do
,if()
, orelse
, 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 withvar
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 asi; ++j
, noti++; j
.The third is well understood, if generally despised.
if (x)\ny()
is equivalent toif (x) { y() }
. The construct doesn’t end until it reaches either a block, or a statement.
;
is a valid JavaScript statement, soif(x);
is equivalent toif(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.