English • Español (Latinoamérica) • Français • Bahasa Indonesia • Italiano (Italian) • 日本語 (Japanese) • 한국어 (Korean) • Português (Brasil) • 简体中文 (Simplified Chinese) • 繁體中文 (Taiwanese Mandarin)
This is a summary of the standard JavaScript rules.
The best way to learn about standard
is to just install it and give it a try on
your code.
eslint: indent
js
function hello (name) {
console.log('hi', name)
}
eslint: quotes
``js
console.log('hello there') // ✓ ok
console.log("hello there") // ✗ avoid
console.log(
hello there`) // ✗ avoid
$("
hello ${name}
) // ✓ ok
```
eslint: no-unused-vars
js
function myFunction () {
var result = something() // ✗ avoid
}
eslint: keyword-spacing
js
if (condition) { ... } // ✓ ok
if(condition) { ... } // ✗ avoid
eslint: space-before-function-paren
```js function name (arg) { ... } // ✓ ok function name(arg) { ... } // ✗ avoid
run(function () { ... }) // ✓ ok run(function() { ... }) // ✗ avoid ```
===
instead of ==
.obj == null
is allowed to check for null || undefined
.eslint: eqeqeq
js
if (name === 'John') // ✓ ok
if (name == 'John') // ✗ avoid
js
if (name !== 'John') // ✓ ok
if (name != 'John') // ✗ avoid
eslint: space-infix-ops
js
// ✓ ok
var x = 2
var message = 'hello, ' + name + '!'
js
// ✗ avoid
var x=2
var message = 'hello, '+name+'!'
eslint: comma-spacing
js
// ✓ ok
var list = [1, 2, 3, 4]
function greet (name, options) { ... }
js
// ✗ avoid
var list = [1,2,3,4]
function greet (name,options) { ... }
eslint: brace-style
js
// ✓ ok
if (condition) {
// ...
} else {
// ...
}
js
// ✗ avoid
if (condition) {
// ...
}
else {
// ...
}
eslint: curly
js
// ✓ ok
if (options.quiet !== true) console.log('done')
js
// ✓ ok
if (options.quiet !== true) {
console.log('done')
}
js
// ✗ avoid
if (options.quiet !== true)
console.log('done')
err
function parameter.eslint: handle-callback-err
js
// ✓ ok
run(function (err) {
if (err) throw err
window.alert('done')
})
js
// ✗ avoid
run(function (err) {
window.alert('done')
})
/* global */
comment.window
, document
, and navigator
.open
, length
,
event
, and name
.```js / global alert, prompt /
alert('hi') prompt('ok?') ```
Explicitly referencing the function or property on window
is okay too, though
such code will not run in a Worker which uses self
instead of window
.
eslint: no-undef
js
window.alert('hi') // ✓ ok
eslint: no-multiple-empty-lines
js
// ✓ ok
var value = 'hello world'
console.log(value)
js
// ✗ avoid
var value = 'hello world'
// blank line
// blank line
console.log(value)
?
and :
on their own lines.eslint: operator-linebreak
```js // ✓ ok var location = env.development ? 'localhost' : 'www.api.com'
// ✓ ok var location = env.development ? 'localhost' : 'www.api.com'
// ✗ avoid var location = env.development ? 'localhost' : 'www.api.com' ```
eslint: one-var
```js // ✓ ok var silent = true var verbose = true
// ✗ avoid var silent = true, verbose = true
// ✗ avoid var silent = true, verbose = true ```
=
) rather than a typo for equality (===
).eslint: no-cond-assign
```js // ✓ ok while ((m = text.match(expr))) { // ... }
// ✗ avoid while (m = text.match(expr)) { // ... } ```
eslint: block-spacing
js
function foo () {return true} // ✗ avoid
function foo () { return true } // ✓ ok
eslint: camelcase
```js function my_function () { } // ✗ avoid function myFunction () { } // ✓ ok
var my_var = 'hello' // ✗ avoid
var myVar = 'hello' // ✓ ok
```
eslint: comma-dangle
js
var obj = {
message: 'hello', // ✗ avoid
}
eslint: comma-style
```js var obj = { foo: 'foo' ,bar: 'bar' // ✗ avoid }
var obj = {
foo: 'foo',
bar: 'bar' // ✓ ok
}
```
eslint: dot-location
```js console. log('hello') // ✗ avoid
console
.log('hello') // ✓ ok
```
eslint: eol-last
eslint: func-call-spacing
js
console.log ('hello') // ✗ avoid
console.log('hello') // ✓ ok
eslint: key-spacing
js
var obj = { 'key' : 'value' } // ✗ avoid
var obj = { 'key' :'value' } // ✗ avoid
var obj = { 'key':'value' } // ✗ avoid
var obj = { 'key': 'value' } // ✓ ok
eslint: new-cap
```js function animal () {} var dog = new animal() // ✗ avoid
function Animal () {} var dog = new Animal() // ✓ ok ```
eslint: new-parens
js
function Animal () {}
var dog = new Animal // ✗ avoid
var dog = new Animal() // ✓ ok
eslint: accessor-pairs
```js var person = { set name (value) { // ✗ avoid this._name = value } }
var person = { set name (value) { this._name = value }, get name () { // ✓ ok return this._name } } ```
super
.eslint: constructor-super
```js class Dog { constructor () { super() // ✗ avoid this.legs = 4 } }
class Dog extends Animal { constructor () { // ✗ avoid this.legs = 4 } }
class Dog extends Animal { constructor () { super() // ✓ ok this.legs = 4 } } ```
eslint: no-array-constructor
js
var nums = new Array(1, 2, 3) // ✗ avoid
var nums = [1, 2, 3] // ✓ ok
arguments.callee
and arguments.caller
.eslint: no-caller
```js function foo (n) { if (n <= 0) return
arguments.callee(n - 1) // ✗ avoid
}
function foo (n) { if (n <= 0) return
foo(n - 1) // ✓ ok
} ```
eslint: no-class-assign
js
class Dog {}
Dog = 'Fido' // ✗ avoid
const
.eslint: no-const-assign
js
const score = 100
score = 125 // ✗ avoid
eslint: no-constant-condition
```js if (false) { // ✗ avoid // ... }
if (x === 0) { // ✓ ok // ... }
while (true) { // ✓ ok // ... } ```
eslint: no-control-regex
js
var pattern = /\x1f/ // ✗ avoid
var pattern = /\x20/ // ✓ ok
debugger
statements.eslint: no-debugger
js
function sum (a, b) {
debugger // ✗ avoid
return a + b
}
delete
operator on variables.eslint: no-delete-var
js
var name
delete name // ✗ avoid
eslint: no-dupe-args
```js function sum (a, b, a) { // ✗ avoid // ... }
function sum (a, b, c) { // ✓ ok // ... } ```
eslint: no-dupe-class-members
js
class Dog {
bark () {}
bark () {} // ✗ avoid
}
eslint: no-dupe-keys
js
var user = {
name: 'Jane Doe',
name: 'John Doe' // ✗ avoid
}
case
labels in switch
statements.eslint: no-duplicate-case
js
switch (id) {
case 1:
// ...
case 1: // ✗ avoid
}
eslint: no-duplicate-imports
```js import { myFunc1 } from 'module' import { myFunc2 } from 'module' // ✗ avoid
import { myFunc1, myFunc2 } from 'module' // ✓ ok ```
eslint: no-empty-character-class
js
const myRegex = /^abc[]/ // ✗ avoid
const myRegex = /^abc[a-z]/ // ✓ ok
eslint: no-empty-pattern
js
const { a: {} } = foo // ✗ avoid
const { a: { b } } = foo // ✓ ok
eval()
.eslint: no-eval
js
eval( "var result = user." + propName ) // ✗ avoid
var result = user[propName] // ✓ ok
catch
clauses.eslint: no-ex-assign
```js try { // ... } catch (e) { e = 'new value' // ✗ avoid }
try { // ... } catch (e) { const newVal = 'new value' // ✓ ok } ```
eslint: no-extend-native
js
Object.prototype.age = 21 // ✗ avoid
eslint: no-extra-bind
```js const name = function () { getName() }.bind(user) // ✗ avoid
const name = function () { this.getName() }.bind(user) // ✓ ok ```
eslint: no-extra-boolean-cast
```js const result = true if (!!result) { // ✗ avoid // ... }
const result = true if (result) { // ✓ ok // ... } ```
eslint: no-extra-parens
js
const myFunc = (function () { }) // ✗ avoid
const myFunc = function () { } // ✓ ok
break
to prevent fallthrough in switch
cases.eslint: no-fallthrough
```js 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() } ```
eslint: no-floating-decimal
js
const discount = .5 // ✗ avoid
const discount = 0.5 // ✓ ok
eslint: no-func-assign
js
function myFunc () { }
myFunc = myOtherFunc // ✗ avoid
eslint: no-global-assign
js
window = {} // ✗ avoid
eval()
.eslint: no-implied-eval
js
setTimeout("alert('Hello world')") // ✗ avoid
setTimeout(function () { alert('Hello world') }) // ✓ ok
eslint: no-inner-declarations
js
if (authenticated) {
function setAuthUser () {} // ✗ avoid
}
RegExp
constructors.eslint: no-invalid-regexp
js
RegExp('[a-z') // ✗ avoid
RegExp('[a-z]') // ✓ ok
eslint: no-irregular-whitespace
js
function myFunc () /*<NBSP>*/{} // ✗ avoid
__iterator__
.eslint: no-iterator
js
Foo.prototype.__iterator__ = function () {} // ✗ avoid
eslint: no-label-var
js
var score = 100
function game () {
score: while (true) { // ✗ avoid
score -= 10
if (score > 0) continue score
break
}
}
eslint: no-labels
js
label:
while (true) {
break label // ✗ avoid
}
eslint: no-lone-blocks
```js function myFunc () { { // ✗ avoid myOtherFunc() } }
function myFunc () { myOtherFunc() // ✓ ok } ```
eslint: no-mixed-spaces-and-tabs
eslint: no-multi-spaces
js
const id = 1234 // ✗ avoid
const id = 1234 // ✓ ok
eslint: no-multi-str
js
const message = 'Hello \
world' // ✗ avoid
new
without assigning object to a variable.eslint: no-new
js
new Character() // ✗ avoid
const character = new Character() // ✓ ok
Function
constructor.eslint: no-new-func
js
var sum = new Function('a', 'b', 'return a + b') // ✗ avoid
Object
constructor.eslint: no-new-object
js
let config = new Object() // ✗ avoid
new require
.eslint: no-new-require
js
const myModule = new require('my-module') // ✗ avoid
Symbol
constructor.eslint: no-new-symbol
js
const foo = new Symbol('foo') // ✗ avoid
eslint: no-new-wrappers
js
const message = new String('hello') // ✗ avoid
eslint: no-obj-calls
js
const math = Math() // ✗ avoid
eslint: no-octal
js
const octal = 042 // ✗ avoid
const decimal = 34 // ✓ ok
const octalString = '042' // ✓ ok
eslint: no-octal-escape
js
const copyright = 'Copyright \251' // ✗ avoid
__dirname
and __filename
.eslint: no-path-concat
js
const pathToFile = __dirname + '/app.js' // ✗ avoid
const pathToFile = path.join(__dirname, 'app.js') // ✓ ok
__proto__
. Use getPrototypeOf
instead.eslint: no-proto
js
const foo = obj.__proto__ // ✗ avoid
const foo = Object.getPrototypeOf(obj) // ✓ ok
eslint: no-redeclare
```js let name = 'John' let name = 'Jane' // ✗ avoid
let name = 'John' name = 'Jane' // ✓ ok ```
eslint: no-regex-spaces
```js const regexp = /test value/ // ✗ avoid
const regexp = /test {3}value/ // ✓ ok const regexp = /test value/ // ✓ ok ```
eslint: no-return-assign
```js function sum (a, b) { return result = a + b // ✗ avoid }
function sum (a, b) { return (result = a + b) // ✓ ok } ```
eslint: no-self-assign
js
name = name // ✗ avoid
eslint: no-self-compare
js
if (score === score) {} // ✗ avoid
eslint: no-sequences
js
if (doSomething(), !!test) {} // ✗ avoid
eslint: no-shadow-restricted-names
js
let undefined = 'value' // ✗ avoid
eslint: no-sparse-arrays
js
let fruits = ['apple',, 'orange'] // ✗ avoid
eslint: no-tabs
eslint: no-template-curly-in-string
js
const message = 'Hello ${name}' // ✗ avoid
const message = `Hello ${name}` // ✓ ok
super()
must be called before using this
.eslint: no-this-before-super
js
class Dog extends Animal {
constructor () {
this.legs = 4 // ✗ avoid
super()
}
}
throw
an Error
object.eslint: no-throw-literal
js
throw 'error' // ✗ avoid
throw new Error('error') // ✓ ok
eslint: no-trailing-spaces
undefined
is not allowed.eslint: no-undef-init
```js let name = undefined // ✗ avoid
let name name = 'value' // ✓ ok ```
eslint: no-unmodified-loop-condition
js
for (let i = 0; i < items.length; j++) {...} // ✗ avoid
for (let i = 0; i < items.length; i++) {...} // ✓ ok
eslint: no-unneeded-ternary
js
let score = val ? val : 0 // ✗ avoid
let score = val || 0 // ✓ ok
return
, throw
, continue
, and break
statements.eslint: no-unreachable
js
function doSomething () {
return true
console.log('never called') // ✗ avoid
}
finally
blocks.eslint: no-unsafe-finally
js
try {
// ...
} catch (e) {
// ...
} finally {
return 42 // ✗ avoid
}
eslint: no-unsafe-negation
js
if (!key in obj) {} // ✗ avoid
if (!(key in obj)) {} // ✓ ok
.call()
and .apply()
.eslint: no-useless-call
js
sum.call(null, 1, 2, 3) // ✗ avoid
eslint: no-useless-computed-key
js
const user = { ['name']: 'John Doe' } // ✗ avoid
const user = { name: 'John Doe' } // ✓ ok
eslint: no-useless-constructor
js
class Car {
constructor () { // ✗ avoid
}
}
eslint: no-useless-escape
js
let message = 'Hell\o' // ✗ avoid
eslint: no-useless-rename
js
import { config as config } from './config' // ✗ avoid
import { config } from './config' // ✓ ok
eslint: no-whitespace-before-property
js
user .name // ✗ avoid
user.name // ✓ ok
with
statements.eslint: no-with
js
with (val) {...} // ✗ avoid
eslint: object-property-newline
```js 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 ```
eslint: padded-blocks
```js if (user) { // ✗ avoid const name = getName()
}
if (user) { const name = getName() // ✓ ok } ```
eslint: rest-spread-spacing
js
fn(... args) // ✗ avoid
fn(...args) // ✓ ok
eslint: semi-spacing
js
for (let i = 0 ;i < items.length ;i++) {...} // ✗ avoid
for (let i = 0; i < items.length; i++) {...} // ✓ ok
eslint: space-before-blocks
js
if (admin){...} // ✗ avoid
if (admin) {...} // ✓ ok
eslint: space-in-parens
js
getName( name ) // ✗ avoid
getName(name) // ✓ ok
eslint: space-unary-ops
js
typeof!admin // ✗ avoid
typeof !admin // ✓ ok
eslint: spaced-comment
```js //comment // ✗ avoid // comment // ✓ ok
/comment/ // ✗ avoid / comment / // ✓ ok ```
eslint: template-curly-spacing
js
const message = `Hello, ${ name }` // ✗ avoid
const message = `Hello, ${name}` // ✓ ok
isNaN()
when checking for NaN
.eslint: use-isnan
js
if (price === NaN) { } // ✗ avoid
if (isNaN(price)) { } // ✓ ok
typeof
must be compared to a valid string.eslint: valid-typeof
js
typeof name === 'undefimed' // ✗ avoid
typeof name === 'undefined' // ✓ ok
eslint: wrap-iife
```js const getName = function () { }() // ✗ avoid
const getName = (function () { }()) // ✓ ok const getName = (function () { })() // ✓ ok ```
*
in yield*
expressions must have a space before and after.eslint: yield-star-spacing
js
yield* increment() // ✗ avoid
yield * increment() // ✓ ok
eslint: yoda
js
if (42 === age) { } // ✗ avoid
if (age === 42) { } // ✓ ok
eslint: semi
js
window.alert('hi') // ✓ ok
window.alert('hi'); // ✗ avoid
(
, [
, `
, or a handful of other unlikely possibilities.This is the only gotcha with omitting semicolons, and standard
protects you from this potential issue.
(The full list is: [
, (
, `
, +
, *
, /
, -
, ,
, .
, but most of these will never appear at the start of a line in real code.)
eslint: no-unexpected-multiline
```js // ✓ ok ;(function () { window.alert('ok') }())
// ✗ avoid (function () { window.alert('ok') }()) ```
```js // ✓ ok ;[1, 2, 3].forEach(bar)
// ✗ avoid [1, 2, 3].forEach(bar) ```
``js
// ✓ ok
;
hello`.indexOf('o')
// ✗ avoid
hello
.indexOf('o')
```
Note: If you're often writing code like this, you may be trying to be too clever.
Clever short-hands are discouraged, in favor of clear and readable expressions, whenever possible.
Instead of this:
js
;[1, 2, 3].forEach(bar)
This is strongly preferred:
js
var nums = [1, 2, 3]
nums.forEach(bar)
All popular code minifiers in use today use AST-based minification, so they can handle semicolon-less JavaScript with no issues (since semicolons are not required 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:
js foo(); [1,2,3].forEach(bar);
you could do this:
js 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.