2.0.0 • Published 3 years ago
@pdonda/jsstyle v2.0.0
Nova JavaScript Style Guide
This style guide is based on standardJS
:large_blue_diamond: Spacing
- Keyword Spacing
- Multiple blank lines not allowed
- Semicolons must have a space after and no space before
- Unary operators must have a space after
- Space before a function declaration parentheses
- Space inside single line blocks
- Space between colon and value in key value pairs
- Do not use multiple spaces
- Use spaces inside comments
- Must have a space before blocks
- The asterisk in yield* expression must have a space before and after
- No whitespace before properties
- No padding within blocks
- No whitespace between spread operators and their expressions
- No space inside parentheses
- No spacing in template strings
- Infix operator must be spaced
:large_blue_diamond: Indentation
:large_blue_diamond: Declaration
- Camelcase when naming variables and functions
- Remove unused variables
- Every variable declaration should have its own statement
- Use array literals instead of array constructors
- Avoid modifying variables declared using const
- No floating decimals
- No multiline strings
- No redeclaring variables
- Avoid assigning variable to itself
- Sparse arrays are not allowed
- Regular string must not contain template literal placeholders
- Initialize to undefined is not allowed
:large_blue_diamond: Operators
- === instead of ==
- Ternary operator
- No ternary operators when simpler alternative exist
- No delete operator on variables
- Avoid unnecessary boolean casts
- typeof must be compared to a valid string
:large_blue_diamond: Comma
:large_blue_diamond: Function
- No duplicate arguments
- No unnecessary parentheses around function expressions
- No space between function identifiers and their invocation
- No function declaration in nested blocks
- Assignment in return statements must be surrounded by parentheses
- Dot should be on same line as method
- Avoid unnecessary function bindings
- Avoid reassigning function declaration
- No label that share a name with an in scope variable
- No unnecessary nested blocks
- Always handle function err parameter
- No reassigning exceptions in catch clauses
- When using try catch and throw only use Error object to throw an error
- No unreachable code after return, throw, continue and break statements
- No flow control statements in finally blocks
- Immediately invoked function expressions (IIFEs) must be wrapped
:large_blue_diamond: Control flow
- Keep else statement on same line as curly braces
- Use curly braces for multiline if statements
- Avoid using const expressions in conditions except for loops
- Avoid comparing variable to itself
- No unmodified conditions of loops
- Avoid Yoda conditions
- Wrap conditional assignments
- No label statements
- No duplicate case labels in switch statements
- Use break to prevent fall-through in switch cases
:large_blue_diamond: Class and Object
- Constructor names must begin with capital letters
- Constructor with no arguments must be invoked with parentheses
- Constructor of derived class must call super
- Super must be called before using this keyword
- Avoid modifying variables of class declaration
- Maintain consistency of newlines between object properties
- Object must contain a getter when a setter is defined
- No duplicate name in class members
- No duplicate keys in object literals
- No new without assigning object to a variable
- No using the Function constructor
- No using the Object constructor
- No using the Symbol constructor
- No calling global object properties as functions
- No unnecessary constructor
:large_blue_diamond: RegExp
- No empty character classes in regular expressions
- No invalid regular expression string in RegExp constructors
- Avoid multiple spaces in regular expressions literals
:large_blue_diamond: General
- Quotes
- Use single import statement per module
- Renaming import export and restructured assignments to the same name is not allowed
- No unnecessary use of escape
- Use isNaN function when checking for NaN
- Avoid semicolons
Spacing
1. Keyword Spacing
if(condition) { ... } // ✗ avoid
if (condition) { ... } // ✓ ok
2. Multiple blank lines not allowed
// ✗ avoid
let value = 'hello world'
console.log(value)
// ✓ ok
let value = 'hello world'
console.log(value)
3. Semicolons must have a space after and no space before
for (let i = 0 ;i < items.length ;i++) {...} // ✗ avoid
for (let i = 0; i < items.length; i++) {...} // ✓ ok
4. Unary operators must have a space after
typeof!admin // ✗ avoid
typeof !admin // ✓ ok
5. Space before a function declaration parentheses
function name(arg) { ... } // ✗ avoid
function name (arg) { ... } // ✓ ok
run(function() { ... }) // ✗ avoid
run(function () { ... }) // ✓ ok
6. Space inside single line blocks
function foo () {return true} // ✗ avoid
function foo () { return true } // ✓ ok
7. Space between colon and value in key value pairs
let obj = { 'key' : 'value' } // ✗ avoid
let obj = { 'key' :'value' } // ✗ avoid
let obj = { 'key':'value' } // ✗ avoid
let obj = { 'key': 'value' } // ✓ ok
8. Do not use multiple spaces
const id = 1234 // ✗ avoid
const id = 1234 // ✓ ok
9. Use spaces inside comments
//comment // ✗ avoid
// comment // ✓ ok
/*comment*/ // ✗ avoid
/* comment */ // ✓ ok
10. Must have a space before blocks
if (admin){...} // ✗ avoid
if (admin) {...} // ✓ ok
11. The asterisk in yield* expression must have a space before and after
yield* increment() // ✗ avoid
yield * increment() // ✓ ok
12. No whitespace before properties
user .name // ✗ avoid
user.name // ✓ ok
13. No padding within blocks
// ✗ avoid
if (user) {
const name = getName()
}
// ✓ ok
if (user) {
const name = getName()
}
14. No whitespace between spread operators and their expressions
fn(... args) // ✗ avoid
fn(...args) // ✓ ok
15. No space inside parentheses
getName( name ) // ✗ avoid
getName(name) // ✓ ok
16. No spacing in template strings
const message = `Hello, ${ name }` // ✗ avoid
const message = `Hello, ${name}` // ✓ ok
17. Infix operator must be spaced
// ✗ avoid
let x=2
let message = 'hello, '+name+'!'
// ✓ ok
let x = 2
let message = 'hello, ' + name + '!'
Indentation
1. Avoid mixing spaces and tabs for indentation use tabs throughout
// ✗ avoid
function add() {
let x = 10; // tab
let y = 10; // tab
return x + y; // 2 spaces
}
// ✓ ok
function add() {
let x = 10; // tab
let y = 10; // tab
return x + y; // tab
}
Declaration
1. Camelcase when naming variables and functions
// ✗ avoid
function my_function () { }
let my_var = 'hello'
// ✓ ok
let myVar = 'hello'
function myFunction () { }
2. Remove unused variables
// ✗ avoid
function add(a, b) {
let c = 10; // unused variable
return a + b;
}
// ✓ ok
function add(a, b) {
return a + b;
}
3. Every variable declaration should have its own statement
// ✗ avoid
let a = 10, b = 10, c = 10;
let a = 10,
b = 10,
c = 10;
// ✓ ok
let a = 10;
let b = 10;
4. Use array literals instead of array constructors
let nums = new Array(1, 2, 3) // ✗ avoid
let nums = [1, 2, 3] // ✓ ok
5. Avoid modifying variables declared using const
const score = 100
score = 125 // ✗ avoid
6. No floating decimals
const discount = .5 // ✗ avoid
const discount = 0.5 // ✓ ok
7. No multiline strings
// ✗ avoid
let x = 'some very \
long text';
// ✓ ok
let x = 'some very long text';
let x = 'some very ' +
'long text';
8. No redeclaring variables
// ✗ avoid
let name = 'John'
let name = 'Jane'
// ✓ ok
let name = 'John'
name = 'Jane'
9. Avoid assigning variable to itself
// ✗ avoid
foo = foo;
[name, age] = [name, age];
// ✓ ok
name = personname;
[a, b] = [b, a];
10. Sparse arrays are not allowed
// ✗ avoid
let fruits = ['apple',, 'orange']
let numbers = [1, 2,,,, 6]
// ✓ ok
let fruits = ['apple', 'banana', 'orange']
let numbers = [1, 2, 3, 4, 5, 6]
11. Regular string must not contain template literal placeholders
// ✗ avoid
let message1 = 'Hello ${name}'
let message2 = "Hello ${name}"
// ✓ ok
const message = `Hello ${name}`
12. Initialize to undefined is not allowed
let name = undefined // ✗ avoid
let name
name = 'value' // ✓ ok
Operators
1. Triple equals operator instead of double equals operator
// ✗ avoid
if (name == 'John') {}
if (name != 'John') {}
// ✓ ok
if (name === 'John') {}
if (name !== 'John') {}
2. Ternary operator
// ✗ avoid
let location = env.development ?
'localhost' :
'www.api.com'
// ✓ ok
let location = env.development ? 'localhost' : 'www.api.com'
_or_
let location = env.development
? 'localhost'
: 'www.api.com'
3. No ternary operators when simpler alternative exist
let score = val ? val : 0 // ✗ avoid
let score = val || 0 // ✓ ok
4. No delete operator on variables
// ✗ avoid
let name
delete name
5. Avoid unnecessary boolean casts
// ✗ avoid
const result = true
if (!!result) {
// code here
}
// ✓ ok
const result = true
if (result) {
// code here
}
6. typeof must be compared to a valid string
typeof name === 'undefimed' // ✗ avoid
typeof name === 'undefined' // ✓ ok
Comma
1. Spacing
// ✗ avoid
let list = [1,2,3,4]
function greet (name,options) { ... }
// ✓ ok
let list = [1, 2, 3, 4]
function greet (name, options) { ... }
2. Style
// ✗ avoid
let person = {
name: 'John'
,age: 28
}
// ✓ ok
let person = {
name: 'John',
age: 28
}
3. Trailing commas not allowed
if (doSomething(), !!test) {} // ✗ avoid
4. Avoid using comma operator
// ✗ avoid
let person = {
name: 'John',
age: 26,
};
// ✓ ok
let person = {
name: 'John',
age: 26
};
Function
1. No duplicate arguments
// ✗ avoid
function sum (a, b, a) {
// code here
}
// ✓ ok
function sum (a, b, c) {
// code here
}
2. No unnecessary parentheses around function expressions
const myFunc = (function () { }) // ✗ avoid
const myFunc = function () { } // ✓ ok
3. No space between function identifiers and their invocation
console.log ('hello') // ✗ avoid
console.log('hello') // ✓ ok
4. No function declaration in nested blocks
// ✗ avoid
if (authenticated) {
function setAuthUser () {}
}
// ✓ ok
if (authenticated) {
// code here
}
function setAuthUser () {
// code here
}
5. Assignment in return statements must be surrounded by parentheses
// ✗ avoid
function sum (a, b) {
return result = a + b
}
// ✓ ok
function sum (a, b) {
return (result = a + b)
}
6. Dot should be on same line as method
// ✗ avoid
console.
log('hello')
// ✓ ok
console
.log('hello')
7. Avoid unnecessary function bindings
// ✗ avoid
const name = function () {
getName()
}.bind(user)
// ✓ ok
const name = function () {
this.getName()
}.bind(user)
8. Avoid reassigning function declaration
// ✗ avoid
function foo() {}
foo = bar;
// ✓ ok
let foo = function () {}
foo = bar;
9. No label that share a name with an in scope variable
// ✗ avoid
let score = 100
function game () {
score: while (true) {
score -= 10
if (score > 0) continue score
break
}
}
// ✓ ok
function foo() {
var q = t;
}
function bar() {
q:
for(;;) {
break q;
}
}
10. No unnecessary nested blocks
// ✗ avoid
function myFunc () {
{
myOtherFunc()
}
}
// ✓ ok
function myFunc () {
myOtherFunc()
}
11. Always handle function err parameter
// ✗ avoid
run(function (err) {
window.alert('done')
})
// ✓ ok
run(function (err) {
if (err) throw err
window.alert('done')
})
12. No reassigning exceptions in catch clauses
// ✗ avoid
try {
// code here
} catch (e) {
e = 'new value'
}
// ✓ ok
try {
// code here
} catch (e) {
const newVal = 'new value'
}
13. When using try catch and throw only use Error object to throw an error
throw 'error' // ✗ avoid
throw new Error('error') // ✓ ok
14. No unreachable code after return, throw, continue and break statements
// ✗ avoid
function foo() {
return true;
console.log("done");
}
function bar() {
throw new Error("Oops!");
console.log("done");
}
while(value) {
break;
console.log("done");
}
function baz() {
if (Math.random() < 0.5) {
return;
} else {
throw new Error();
}
console.log("done");
}
// ✓ ok
function foo() {
return bar();
function bar() {
return 1;
}
}
function bar() {
return x;
let x;
}
switch (foo) {
case 1:
break;
let x;
}
15. No flow control statements in finally blocks
// ✗ avoid
let foo = function() {
try {
return 1;
} catch(err) {
return 2;
} finally {
return 3;
}
};
// ✓ ok
let foo = function() {
try {
return 1;
} catch(err) {
return 2;
} finally {
console.log("hola!");
}
};
let foo = function() {
try {
return 1;
} catch(err) {
return 2;
} finally {
let a = function() {
return "hola!";
}
}
};
let foo = function() {
try {
return 1;
} catch(err) {
return 2;
} finally {
switch(a) {
case 1: {
console.log("hola!")
break;
}
}
}
};
16. Immediately invoked function expressions (IIFEs) must be wrapped
const getName = function () { }() // ✗ avoid
const getName = (function () { }()) // ✓ ok
const getName = (function () { })() // ✓ ok
Control flow
1. Keep else statement on same line as curly braces
// ✗ avoid
if (condition) {
// code here
}
else {
// code here
}
// ✓ ok
if (condition) {
// code here
} else {
// code here
}
2. Use curly braces for multiline if statements
// ✗ avoid
if (options.quiet !== true)
console.log('done')
// ✓ ok
if (options.quiet !== true) console.log('done')
if (options.quiet !== true) {
console.log('done')
}
3. Avoid using const expressions in conditions (except loops)
// ✗ avoid
if (false) {
// code here
}
// ✓ ok
if (x === 0) {
// code here
}
while (true) {
// code here
}
4. Avoid comparing variable to itself
if (score === score) {} // ✗ avoid
5. No unmodified conditions of loops
for (let i = 0; i < items.length; j++) {...} // ✗ avoid
for (let i = 0; i < items.length; i++) {...} // ✓ ok
6. Avoid Yoda conditions
if (42 === age) { } // ✗ avoid
if (age === 42) { } // ✓ ok
7. Wrap conditional assignments
// ✗ avoid
while (m = text.match(expr)) {
// code here
}
// ✓ ok
while ((m = text.match(expr))) {
// code here
}
8. No label statements
// ✗ avoid
label:
while(true) {
continue label;
}
// ✓ ok
let f = {
label: "foo"
};
while (true) {
break;
}
9. No duplicate case labels in switch statements
// ✗ avoid
switch (a) {
case one:
break;
case 2:
break;
case one:
break;
default:
break;
}
// ✓ ok
switch (a) {
case 1:
break;
case 2:
break;
case 3:
break;
default:
break;
}
10. Use break to prevent fall-through in switch cases
// ✗ avoid
switch (filter) {
case 1:
doSomething()
case 2:
doSomethingElse()
}
// ✓ ok
switch (filter) {
case 1:
doSomething()
break
case 2:
doSomethingElse()
}
Class and Object
1. Constructor names must begin with capital letters
function animal () {}
let dog = new animal() // ✗ avoid
function Animal () {}
let dog = new Animal() // ✓ ok
2. Constructor with no arguments must be invoked with parentheses
function Animal () {}
let dog = new Animal // ✗ avoid
let dog = new Animal() // ✓ ok
3. Constructor of derived class must call super
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
}
}
4. Super must be called before using this keyword
// ✗ avoid
class A extends B {
constructor() {
this.a = 0;
super();
}
}
// ✓ ok
class A extends B {
constructor() {
super();
this.a = 0;
}
}
5. Avoid modifying variables of class declaration
// ✗ avoid
class A { }
A = 0;
// ✓ ok
let A = class A { }
A = 0; // A is a variable.
6. Maintain consistency of newlines between object properties
// ✗ avoid
const user = {
name: 'Jane Doe', age: 30,
username: 'jdoe86'
}
// ✓ ok
const user = { name: 'Jane Doe', age: 30, username: 'jdoe86' }
const user = {
name: 'Jane Doe',
age: 30,
username: 'jdoe86'
}
7. Object must contain a getter when a setter is defined
// ✗ avoid
let person = {
set name (value) {
this._name = value
}
}
// ✓ ok
let person = {
set name (value) {
this._name = value
},
get name () {
return this._name
}
}
8. No duplicate name in class members
// ✗ avoid
class Foo {
bar() { }
bar() { }
}
// ✓ ok
class Foo {
bar() { }
qux() { }
}
9. No duplicate keys in object literals
// ✗ avoid
let foo = {
bar: "baz",
bar: "qux"
};
// ✓ ok
let foo = {
bar: "baz",
qux: "qux"
};
10. No new without assigning object to a variable
new Character() // ✗ avoid
const character = new Character() // ✓ ok
11. No using the Function constructor
// ✗ avoid
let x = new Function("a", "b", "return a + b");
let x = Function("a", "b", "return a + b");
// ✓ ok
let x = function (a, b) {
return a + b;
};
12. No using the Object constructor
// ✗ avoid
let myObject = new Object();
new Object();
// ✓ ok
let myObject = new CustomObject();
let myObject = {};
let Object = function Object() {};
new Object();
13. No using the Symbol constructor
// ✗ avoid
let foo = new Symbol('foo');
// ✓ ok
let foo = Symbol('foo');
function bar(Symbol) {
const baz = new Symbol("baz");
}
14. No calling global object properties as functions
// ✗ avoid
let math = Math();
let newMath = new Math();
let json = JSON();
let newJSON = new JSON();
// ✓ ok
function area(r) {
return Math.PI * r * r;
}
let object = JSON.parse("{}");
15. No unnecessary constructor
// ✗ avoid
class A {
constructor () {
}
}
class B extends A {
constructor (...args) {
super(...args);
}
}
// ✓ ok
class A { }
class A {
constructor () {
doSomething();
}
}
RegExp
1. No empty character classes in regular expressions
const myRegex = /^abc[]/ // ✗ avoid
const myRegex = /^abc[a-z]/ // ✓ ok
2. No invalid regular expression string in RegExp constructors
RegExp('[a-z') // ✗ avoid
RegExp('[a-z]') // ✓ ok
3. Avoid multiple spaces in regular expressions literals
const regexp = /test value/ // ✗ avoid
const regexp = /test {3}value/ // ✓ ok
const regexp = /test value/ // ✓ ok
General
1. Quotes
console.log("hello there") // ✗ avoid
console.log(`hello there`) // ✗ avoid
console.log('hello there') // ✓ ok
$("<div class='box'>") // ✓ ok
console.log(`hello ${name}`) // ✓ ok
2. Use single import statement per module
import { myFunc1 } from 'module'
import { myFunc2 } from 'module' // ✗ avoid
import { myFunc1, myFunc2 } from 'module' // ✓ ok
3. Renaming import export and restructured assignments to the same name is not allowed
import { config as config } from './config' // ✗ avoid
import { config } from './config' // ✓ ok
4. No unnecessary use of escape
let message = 'Hell\o' // ✗ avoid
5. Use isNaN function when checking for NaN
if (price === NaN) { } // ✗ avoid
if (isNaN(price)) { } // ✓ ok
6. Avoid semicolons
window.alert('hi') // ✗ avoid
window.alert('hi'); // ✓ ok