preface

This post is based on a Github project Airbnb /javascript translation, with some personal understanding added. Specification helps us to improve code readability and avoid unnecessary bugs. However, there is no unified standard and hard requirements, here is just to provide you with some reference, suitable for the team and their own is the best.

Personal Blog Address🍹 🍰 fe – code

type

  • 1.1 Basic Types

When assigning a primitive type, you should use the value of the type directly

  • string
  • number
  • boolean
  • null
  • undefined
  • symbol
const foo = 1;
let bar = foo;

bar = 9;

console.log(foo, bar); / / = > 1, 9
Copy the code
  • The complex type

Complex type assignments are really references to addresses

  • object
  • array
  • function
const foo = [1.2];
const bar = foo;

bar[0] = 9;

console.log(foo[0], bar[0]); / / = > 9, 9
// const only prevents reassignment of reference type addresses
// There is no guarantee that the attributes of a reference type are invariant
Copy the code

The use of states

  • 2.1 All assignments are usedconst, avoid usingvar. eslint: prefer-const.no-const-assign

Try to make sure that the state in your code is manageable, and repeated references can lead to bugs and code that are hard to understand.

// bad
var a = 1;
var b = 2;

// good
const a = 1;
const b = 2;
Copy the code
  • 2.2 If you must reassign a parameter, do soletRather thanvar. eslint: no-var

Let is the block-level scope, var is the function level scope, also to reduce the code uncontrollable, reduce “accidents”

// bad
var count = 1;
if (true) {
  count += 1;
}

// good, use the let.
let count = 1;
if (true) {
  count += 1;
}
Copy the code
  • 2.3 let,constBoth are block-level scopes
// Both const and let exist only in the block-level scope it defines
{
  let a = 1;
  const b = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
Copy the code

object

  • 3.1 Creating Objects using Literals ESLint: no-new-object
// bad
const item = new Object(a);// good
const item = {};
Copy the code
  • 3.2 When creating an object with dynamic property names, place all defined properties in one place of the object.

function getKey(k) {
  return `a key named ${k}`;
}

// bad
const obj = {
  id: 5.name: 'San Francisco'}; obj[getKey('enabled')] = true;

// Good getKey('enabled') is the dynamic attribute name
const obj = {
  id: 5.name: 'San Francisco',
  [getKey('enabled')]: true};Copy the code
  • 3.3 Method shorthand: ESLint: Object-Shorthand
// bad
const atom = {
  value: 1.addValue: function (value) {
    returnatom.value + value; }};// good
const atom = {
  value: 1.// Object method
  addValue(value) {
    returnatom.value + value; }};Copy the code
  • 3.4 Attribute Value Abbreviation ESLint: Object-Shorthand
const lukeSkywalker = 'Luke Skywalker';

// bad
const obj = {
  lukeSkywalker: lukeSkywalker,
};

// good
const obj = {
  lukeSkywalker
};
Copy the code
  • 3.5 Place property abbreviations at the beginning of object declarations.
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';

// bad
const obj = {
  episodeOne: 1.twoJediWalkIntoACantina: 2,
  lukeSkywalker,
  episodeThree: 3.mayTheFourth: 4,
  anakinSkywalker,
};

// good
const obj = {
  lukeSkywalker,
  anakinSkywalker,
  episodeOne: 1.twoJediWalkIntoACantina: 2.episodeThree: 3.mayTheFourth: 4};Copy the code
  • 3.6 Use quotation marks only for invalid identifiers' '. eslint: quote-props

In general, we think it’s subjectively easier to read. It improves syntax highlighting and is easier to optimize by the JS engine.

// bad
const bad = {
  'foo': 3.'bar': 4.'data-blah': 5};// good
const good = {
  foo: 3.bar: 4.'data-blah': 5};Copy the code
  • 3.7 Do not call directlyObject.prototypeOn, such ashasOwnProperty.propertyIsEnumerable.isPrototypeOf.

On problematic objects, these methods may be masked – {hasOwnProperty: false} – or it may be an empty object.create (null).

// bad
console.log(object.hasOwnProperty(key));

// good
console.log(Object.prototype.hasOwnProperty.call(object, key));

// best
const has = Object.prototype.hasOwnProperty; // do a cache in the module
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
// ...
console.log(has.call(object, key));
Copy the code
  • 3.8 Extended operators are recommended for shallow copy of objects.Rather thanObject.assign. The REST operator is recommended when destructuring assignment to obtain several properties specified by an object, as well..
// very bad
const original = { a: 1.b: 2 };
const copy = Object.assign(original, { c: 3 }); 
delete copy.a; // So does this change original

// bad
const original = { a: 1.b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }

// good
const original = { a: 1.b: 2 };
constcopy = { ... original,c: 3 }; // copy => { a: 1, b: 2, c: 3 }

const{ a, ... noA } = copy;// noA => { b: 2, c: 3 }
Copy the code

An array of

  • 4.1 Assigning values using literals. eslint: no-array-constructor
// bad
const items = new Array(a);// good
const items = [];
Copy the code
  • 4.2 Add a value to an array with Array#push instead of using subscripts directly.
const someStack = [];

// bad
someStack[someStack.length] = 'abracadabra';

// good
someStack.push('abracadabra');
Copy the code
  • 4.3 Shallow copy of array with extension operator, similar to shallow copy of object above
// bad
const len = items.length;
const itemsCopy = [];
let i;

for (i = 0; i < len; i += 1) {
  itemsCopy[i] = items[i];
}

// good
const itemsCopy = [...items];
Copy the code
  • 4.4 recommended.Operator instead ofArray.fromTo convert an array of classes to an array.
const foo = document.querySelectorAll('.foo');

// good
const nodes = Array.from(foo);

// best
const nodes = [...foo];
Copy the code
  • 4.5 Convert an array-like object to an Array using array. from.
const arrLike = { 0: 'foo'.1: 'bar'.2: 'baz'.length: 3 };

// bad
const arr = Array.prototype.slice.call(arrLike);

// good
const arr = Array.from(arrLike);
Copy the code
  • 4.6 withArray.fromRather than.Operator to iterate. This avoids creating an intermediate array.
// bad
const baz = [...foo].map(bar);

// good
const baz = Array.from(foo, bar);
Copy the code
  • 4.7 Use return statements in callback functions of array methods. If the function body consists of a statement that returns an expression and that expression has no side effects, return can be ignored, as shown in 8.2. esLint: array-callback-return
// good
[1.2.3].map((x) = > {
  const y = x + 1;
  return x * y;
});

The good function has only one statement
[1.2.3].map(x= > x + 1);

// Bad returns no value, resulting in acc becoming undefined after the first iteration
[[0.1], [2.3], [4.5]].reduce((acc, item, index) = > {
  const flatten = acc.concat(item);
  acc[index] = flatten;
});

// good
[[0.1], [2.3], [4.5]].reduce((acc, item, index) = > {
  const flatten = acc.concat(item);
  acc[index] = flatten;
  return flatten;
});

// bad
inbox.filter((msg) = > {
  const { subject, author } = msg;
  if (subject === 'Mockingbird') {
    return author === 'Harper Lee';
  } else {
    return false; }});// good
inbox.filter((msg) = > {
  const { subject, author } = msg;
  if (subject === 'Mockingbird') {
    return author === 'Harper Lee';
  }

  return false;
});
Copy the code
  • 4.8 If an array has many rows, the[And after]Before the line break.
// bad
const arr = [
  [0.1], [2.3], [4.5]];const objectInArray = [{
  id: 1}, {id: 2,}];const numberInArray = [
  1.2,];// good
const arr = [[0.1], [2.3], [4.5]].const objectInArray = [
  {
    id: 1}, {id: 2,},];const numberInArray = [
  1.2,];Copy the code

deconstruction

  • 5.1 Use deconstructive assignment of objects to obtain and use one or more attribute values of objects. eslint: prefer-destructuring

This eliminates the need to create temporary/references to these attributes

// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;

  return `${firstName} ${lastName}`;
}

// good
function getFullName(user) {
  const { firstName, lastName } = user;
  return `${firstName} ${lastName}`;
}

// best
function getFullName({ firstName, lastName }) {
  return `${firstName} ${lastName}`;
}
Copy the code
  • 5.2 Array deconstruction.
const arr = [1.2.3.4];

// bad
const first = arr[0];
const second = arr[1];

// good
const [first, second] = arr;
Copy the code
  • 5.3 Multiple return values are deconstructed by objects, not arrays.

Independent of the order of return values, more readable

// bad
function processInput(input) {
  // Then there is the miracle
  return [left, right, top, bottom];
}

const [left, __, top] = processInput(input);

// good
function processInput(input) {
  return { left, right, top, bottom };
}

const { left, top } = processInput(input);
Copy the code

string

  • 6.1 Single Quotation marks are Used for Strings' '. eslint:quotes
// bad
const name = "Capt. Janeway";

// bad - The template should contain insert text or line breaks
const name = `Capt. Janeway`;

// good
const name = 'Capt. Janeway';
Copy the code
  • 6.2 Should not be used+Concatenate a newline string.

Difficult to use and unreadable

// bad
const errorMessage = 'This is a super long error that was thrown because \ of Batman. When you stop to think about how Batman had anything to  do \ with this, you would get nowhere \ fast.';

// bad
const errorMessage = 'This is a super long error that was thrown because ' +
  'of Batman. When you stop to think about how Batman had anything to do ' +
  'with this, you would get nowhere fast.';

// good
const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
Copy the code
  • 6.3 Use string templates instead of+To concatenate strings. eslint:prefer-template template-curly-spacing

Template strings are more readable, syntax concise, and string insertion arguments.

// bad
function sayHi(name) {
  return 'How are you, ' + name + '? ';
}

// bad
function sayHi(name) {
  return ['How are you, ', name, '? '].join();
}

// bad
function sayHi(name) {
  return `How are you, ${ name }? `;
}

// good
function sayHi(name) {
  return `How are you, ${name}? `;
}
Copy the code
  • 6.4 Never use in a stringeval(), too many loopholes. eslint:no-eval
  • 6.5 Do not use unnecessary escape characters. eslint: no-useless-escape

Backslashes are unreadable and should only be used when necessary

// bad
const foo = '\'this\' \i\s \"quoted\"';

// good
const foo = '\'this\' is "quoted"';

//best
const foo = `my name is '${name}'`;
Copy the code

function

  • 7.1 Use named function expressions instead of function declarations. eslint: func-style

Function declaration scope increases, reducing code readability and maintainability. If you find that a function is too large and complex to make sense of the rest of the file, it might be time to split the function into a separate module. (Discussion)

// bad
function foo() {
  // ...
}

// bad
const foo = function () {
  // ...
};

// good

const short = function longUniqueMoreDescriptiveLexicalFoo() {
  // ...
};
Copy the code
  • 7.2 Enclose immediate functions in parentheses. eslint: wrap-iife

An immediate function expression is a unit – enclosing it with its caller (parentheses). Of course, in modern module development, you don’t need much of it.

// immediately-invoked function expression (IIFE)
(function () {
  console.log('Welcome to the Internet. Please follow me.'); } ());Copy the code
  • 7.3 Do not declare functions inside non-function blocks (if, while, etc.). I’m going to assign this function to a variable. Browsers will allow you to do this, but the results may differ depending on how browsers parse. Eslint: no-loop-func esLint: no-loop-func

  • 7.4 Note: In ECMA-262, a block is defined as a series of statements; But a function declaration is not a statement. A function expression is a statement.

// bad
if (currentUser) {
  function test() {
    console.log('Nope.'); }}// good
let test;
if (currentUser) {
  test = (a)= > {
    console.log('Yup.');
  };
}
Copy the code
  • 7.5 Never use itargumentsNamed parameters. It takes precedence over the one inherent in each function scopeargumentsObject, so it causes the function to be nativeargumentsThe value is overwritten.
// bad
function foo(name, options, arguments) {
  // ...
}

// good
function foo(name, options, args) {
  // ...
}
Copy the code
  • 7.6 Rest Syntax is preferred.Rather thanarguments. eslint:prefer-rest-params

. Be more specific about which parameters you want to use.

// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args.join(' ');
}

// good
function concatenateAll(. args) {
  return args.join(' ');
}
Copy the code
  • 7.8 Use default parameter syntax instead of reassigning parameters in functions.
// really bad
function handleThings(opts) {
  // Although you want to write this way, this introduces some subtle bugs
  // If opts is false, it will be assigned {}
  opts = opts || {};
  // ...
}

// still bad
function handleThings(opts) {
  if (opts === void 0) {
    opts = {};
  }
  // ...
}

// good
function handleThings(opts = {}) {
  // ...
}
Copy the code
  • 7.8 Avoid side effects when using default parameters
var b = 1;
// bad
function count(a = b++) {
  console.log(a);
}
count();  / / 1
count();  / / 2
count(3); / / 3
count();  / / 3
// It's easy to get confused
Copy the code
  • 7.9 Leave default Parameter assignments last
// bad
function handleThings(opts = {}, name) {
  // ...
}

// good
function handleThings(name, opts = {}) {
  // ...
}
Copy the code
  • 7.10 Do not create functions with Function. eslint: no-new-func
// bad
var add = new Function('a'.'b'.'return a + b');

// still bad
var subtract = Function('a'.'b'.'return a - b');
Copy the code
  • 7.11 Function signatures must contain Spaces. eslint: space-before-function-paren space-before-blocks
// bad
const f = function(){};
const g = function (){};
const h = function() {};

// good
const x = function () {};
const y = function a() {};
Copy the code
  • 7.12 Never change parameters ESLint: no-param-reassign

Pay special attention to operations on reference types to ensure immutability of data

// bad
function f1(obj) {
  obj.key = 1;
};

// good
function f2(obj) {
  const key = Object.prototype.hasOwnProperty.call(obj, 'key')? obj.key :1;
};
Copy the code
  • 7.13 Do not reassign parameters. eslint: no-param-reassign
// bad
function f1(a) {
  a = 1;
  // ...
}

function f2(a) {
  if(! a) { a =1; }
  // ...
}

// good
function f3(a) {
  const b = a || 1;
  // ...
}

function f4(a = 1) {
  // ...
}
Copy the code
  • 7.14 use.. eslint:prefer-spread

Why? It’s clearer, you don’t have to provide context, and you can’t easily compose new with Apply

// bad
const x = [1.2.3.4.5];
console.log.apply(console, x);

// good
const x = [1.2.3.4.5];
console.log(... x);// bad
new (Function.prototype.bind.apply(Date[null.2016.8.5]));

// good
new Date(... [2016.8.5]);
Copy the code
  • 7.15 Functions with more than one argument should be written like the other lines of code in this guide: each line has only one argument and each line ends with a comma.
// bad
function foo(bar, baz, quux) {
  // ...
}

// good
function foo(bar, baz, quux,) {
  // ...
}

// bad
console.log(foo,
  bar,
  baz);

// good
console.log(
  foo,
  bar,
  baz,
);
Copy the code

Arrow function

  • 8.1 To use anonymous functions for callbacks, it is best to use the arrow functions eslint: prefer-arrow-callback, arrow-spacing

It creates a function that executes in context, which is usually what you want, and a much cleaner syntax.

// bad
[1.2.3].map(function (x) {
  const y = x + 1;
  return x * y;
});

// good
[1.2.3].map((x) = > {
  const y = x + 1;
  return x * y;
});
Copy the code
  • 8.2 If the function body is composed of aexpressionIs a single statement, without braces and return. Otherwise, keep the braces and use themreturnStatements. eslint:arrow-parens.arrow-body-style
// bad
[1.2.3].map(number= > {
  const nextNumber = number + 1;
  `A string containing the ${nextNumber}. `;
});

// good
[1.2.3].map(number= > `A string containing the ${number}. `);

// good
[1.2.3].map((number) = > {
  const nextNumber = number + 1;
  return `A string containing the ${nextNumber}. `;
});

// good
[1.2.3].map((number, index) = > ({
  [index]: number
}));

Do not use implicit returns if the expression has side effects
function foo(callback) {
  const val = callback();
  if (val === true) {
    // Do something if callback returns true}}let bool = false;

// bad
foo((a)= > bool = true);

// good
foo((a)= > {
  bool = true;
});
Copy the code
  • 8.3 If the expression has more than one line, it is more readable to put the first and last lines in parentheses.
// bad
['get'.'post'.'put'].map(httpMethod= > Object.prototype.hasOwnProperty.call(
    httpMagicObjectWithAVeryLongName,
    httpMethod
  )
);

// good
['get'.'post'.'put'].map(httpMethod= > (
  Object.prototype.hasOwnProperty.call(
    httpMagicObjectWithAVeryLongName,
    httpMethod
  )
));
Copy the code
  • 8.4 Always surround arguments with parentheses esLint: arrow-parens for clarity and consistency
// bad
[1.2.3].map((x) = > x * x);

// good
[1.2.3].map(x= > x * x);

// good
[1.2.3].map(number= > (
  `A long string with the ${number}It's so long that we don't want It to take up space on the. Map line! `
));

// bad
[1.2.3].map(x= > {
  const y = x + 1;
  return x * y;
});

// good
[1.2.3].map((x) = > {
  const y = x + 1;
  return x * y;
});
Copy the code
  • 8.5Avoid arrow function syntax= >And comparison operators< =, > =Confusion. Eslint:no-confusing-arrow
// bad
const itemHeight = item= > item.height > 256 ? item.largeSize : item.smallSize;

// bad
const itemHeight = (item) = > item.height > 256 ? item.largeSize : item.smallSize;

// good
const itemHeight = item= > (item.height > 256 ? item.largeSize : item.smallSize);

// good
const itemHeight = (item) = > {
  const { height, largeSize, smallSize } = item;
  return height > 256 ? largeSize : smallSize;
};
Copy the code
  • 8.6 Use implicit returns to constrain function bodies after arrows. eslint: implicit-arrow-linebreak
// bad
(foo) =>
  bar;

(foo) = >
  (bar);

// good
(foo) => bar;
(foo) = > (bar);
(foo) = > (
   bar
)
Copy the code

Class and constructor

  • 9.1 always useclassAvoid direct operationsprototype
// bad
function Queue(contents = []) {
  this.queue = [...contents];
}
Queue.prototype.pop = function () {
  const value = this.queue[0];
  this.queue.splice(0.1);
  return value;
};


// good
class Queue {
  constructor(contents = []) {
    this.queue = [...contents];
  }
  pop() {
    const value = this.queue[0];
    this.queue.splice(0.1);
    returnvalue; }}Copy the code
  • 9.2 the use ofextendsImplementation inheritance

Built-in methods to inherit archetypes without breaking Instanceof

// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
  Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function () {
  return this._queue[0];
}

// good
class PeekableQueue extends Queue {
  peek() {
    return this._queue[0]; }}Copy the code
  • The 9.3 method can returnthisTo implement the method chain
// bad
Jedi.prototype.jump = function () {
  this.jumping = true;
  return true;
};

Jedi.prototype.setHeight = function (height) {
  this.height = height;
};

const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined

// good
class Jedi {
  jump() {
    this.jumping = true;
    return this;
  }

  setHeight(height) {
    this.height = height;
    return this; }}const luke = new Jedi();

luke.jump()
  .setHeight(20);
Copy the code
  • 9.4 It is possible to write a custom toString() method, but ensure that it works and has no side effects
class Jedi {
  constructor(options = {}) {
    this.name = options.name || 'no name';
  }

  getName() {
    return this.name;
  }

  toString() {
    return `Jedi - The ${this.getName()}`; }}Copy the code
  • 9.5 Classes have a default constructor unless otherwise specified. You don’t have to write an empty constructor or a constructor that just represents the parent class. eslint: no-useless-constructor
// bad
class Jedi {
  constructor() {}

  getName() {
    return this.name; }}// bad
class Rey extends Jedi {
  // This constructor is not required to be written
  constructor(... args) {super(...args);
  }
}

// good
class Rey extends Jedi {
  constructor(... args) {super(... args);this.name = 'Rey'; }}Copy the code
  • 9.6 Avoiding duplicate class members. eslint: no-dupe-class-members

Repeating class members silently execute the last one, and any repetition is definitely an error

// bad
class Foo {
  bar() { return 1; }
  bar() { return 2; }}// good
class Foo {
  bar() { return 1; }}// good
class Foo {
  bar() { return 2; }}Copy the code

The module

  • 10.1 For Use on non-standard module systems (import/export). Or switch to another preferred module system at any time.
// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;

// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;

// best
import { es6 } from './AirbnbStyleGuide';
export default es6;
Copy the code
  • 10.2 Do not use the import * wildcard character
// bad
import * as AirbnbStyleGuide from './AirbnbStyleGuide';

// good
import AirbnbStyleGuide from './AirbnbStyleGuide';
Copy the code
  • 10.3 Do not export directly from import

It looks neat, but affects readability

// bad
// filename es6.js
export { es6 as default } from './AirbnbStyleGuide';

// good
// filename es6.js
import { es6 } from './AirbnbStyleGuide';
export default es6;
Copy the code
  • 10.4 Import an entry only once. eslint: no-duplicate-imports

Why? Importing multiple lines from the same path makes the code difficult to maintain

// bad
import foo from 'foo';
/ /... Some other imports... //
import { named1, named2 } from 'foo';

// good
import foo, { named1, named2 } from 'foo';

// good
import foo, {
  named1,
  named2,
} from 'foo';
Copy the code
  • 10.5 Do not export mutable bindings esLint: import/ no-exports

Minimize states to ensure data immutability. Although this technique may be required in some scenarios, in general constants should be exported.

// bad
let foo = 3;
export { foo }

// good
const foo = 3;
export { foo }
Copy the code
  • 10.6 In a module with only one export, useexport defaultFor the better. eslint:import/prefer-default-export

Encourage more files, do one thing per file and export for better readability and maintainability.

// bad
export function foo() {}

// good
export default function foo() {}
Copy the code
  • 10.7 importBefore all other statements. eslint:import/first

Prevent unexpected behavior.

// bad
import foo from 'foo';
foo.init();

import bar from 'bar';

// good
import foo from 'foo';
import bar from 'bar';

foo.init();
Copy the code
  • 10.8 Multi-line import should be indented, just like multi-line arrays and object literals
// bad
import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';

// good
import {
  longNameA,
  longNameB,
  longNameC,
  longNameD,
  longNameE,
} from 'path';
Copy the code
  • 10.9 Webpack Loader syntax not allowed in import statements ESlint: import/no-webpack-loader-syntax

It is best to write in webpack.config.js

// bad
import fooSass from 'css! sass! foo.scss';
import barCss from 'style! css! bar.css';

// good
import fooSass from 'foo.scss';
import barCss from 'bar.css';
Copy the code

Iterators and generators

  • 11.1 Do not use iterators. Use JavaScript higher-order functions insteadfor-in,for-of. eslint:no-iterator no-restricted-syntax

The immutable rule makes it easier to handle the return value of a pure function than the side effects.

Iterating arrays: map()/every()/filter()/find()/findIndex()/reduce()/some() /… Keys ()/object.values ()/object.entries () to generate an array so that you can traverse the Object.

const numbers = [1.2.3.4.5];

// bad
let sum = 0;
for (let num of numbers) {
  sum += num;
}
sum === 15;

// good
let sum = 0;
numbers.forEach(num= > sum += num);
sum === 15;

// best (use the functional force)
const sum = numbers.reduce((total, num) = > total + num, 0);
sum === 15;

// bad
const increasedByOne = [];
for (let i = 0; i < numbers.length; i++) {
  increasedByOne.push(numbers[i] + 1);
}

// good
const increasedByOne = [];
numbers.forEach(num= > increasedByOne.push(num + 1));

// best (keeping it functional)
const increasedByOne = numbers.map(num= > num + 1);
Copy the code
  • 11.2 Do not use generators now

Poor compatibility

  • 11.3 If you must use them, or if you ignore our advice, make sure the Spaces between their function signatures are correct. eslint: generator-star-spacing

Function and * are the same concept. The keyword * is not a modifier of function. Function * is a unique structure that is different from function

// bad
function * foo() {
  // ...
}

// bad
const bar = function * () {
  // ...
}

// bad
const baz = function* () {
  // ...
}

// bad
const quux = function* () {
  // ...
}

// bad
function*foo() {
  // ...
}

// bad
function *foo() {
  // ...
}

// very bad
function
*
foo() {
  // ...
}

// very bad
const wat = function
*
() {
  // ...
}

// good
function* foo() {
  // ...
}

// good
const foo = function* () {
  // ...
}
Copy the code

attribute

  • 12.1 Use dot notation when accessing attributes esLint: dot-notation
const luke = {
  jedi: true.age: 28};// bad
const isJedi = luke['jedi'];

// good
const isJedi = luke.jedi;
Copy the code
  • 12.2 Square brackets are used when the obtained attribute is a variable[]
const luke = {
  jedi: true.age: 28};function getProp(prop) {
  return luke[prop];
}

const isJedi = getProp('jedi');
Copy the code
  • 12.3 Exponentiation operators are used for exponentiation operations**. eslint:no-restricted-properties.
// bad
const binary = Math.pow(2.10);

// good
const binary = 2 ** 10;
Copy the code

variable

  • 13.1 always useconstletDeclare variables. If you don’t want to run into a pair of variable promotion, global variable bugs. eslint:no-undef prefer-const
// bad
superPower = new SuperPower();

// good
const superPower = new SuperPower();
Copy the code
  • 13.2 Use one for each variable separatelyconstlet. eslint:one-var
// bad
const items = getItems(),
    goSportsTeam = true,
    dragonball = 'z';

// bad
// (compare to above, and try to spot the mistake)
const items = getItems(),
    goSportsTeam = true;
    dragonball = 'z';

// good
const items = getItems();
const goSportsTeam = true;
const dragonball = 'z';
Copy the code
  • 13.3 constPut together,letPut together

This is helpful when the new variable depends on the previous variable or constant

// bad
let i, len, dragonball,
    items = getItems(),
    goSportsTeam = true;

// bad
let i;
const items = getItems();
let dragonball;
const goSportsTeam = true;
let len;

// good
const goSportsTeam = true;
const items = getItems();
let dragonball;
let i;
let length;
Copy the code
  • 13.4 Variable declarations are in place
// bad - unnecessary function call
function checkName(hasName) {
  const name = getName();

  if (hasName === 'test') {
    return false;
  }

  if (name === 'test') {
    this.setName(' ');
    return false;
  }

  return name;
}

// good
function checkName(hasName) {
  if (hasName === 'test') {
    return false;
  }

  // Allocate as needed
  const name = getName();

  if (name === 'test') {
    this.setName(' ');
    return false;
  }

  return name;
}
Copy the code
  • 13.5 Do not use continuous variable assignments. eslint: no-multi-assign

Why? Link variable assignments create implicit global variables.

// bad
(function example() {
  // JavaScript interprets it as
  // let a = ( b = ( c = 1 ) );
  // let only works on variable A; Both variables B and c become global variables
  let a = b = c = 1; } ());console.log(a); // undefined
console.log(b); / / 1
console.log(c); / / 1

// good
(function example() {
  let a = 1;
  let b = a;
  letc = a; } ());console.log(a); // undefined
console.log(b); // undefined
console.log(c); // undefined

// 'const' also
Copy the code
  • 13.6 Do not use unary increment decrement operators (++.--). Eslintno-plusplus

According to the ESLint documentation, unary increment and decrement statements are affected by automatic semicolon insertion and can cause silent errors that increase or decrease values in your application. It is also more expressive to use num+ = 1 instead of num++ or substitute statements to change your value. Disallowing unary increment and decrement statements also prevents you from inadvertently pre-increment/pre-decrement values, thus reducing unexpected behavior in your program.

  // bad

  let array = [1.2.3];
  let num = 1;
  num++;
  --num;

  let sum = 0;
  let truthyCount = 0;
  for(let i = 0; i < array.length; i++){
    let value = array[i];
    sum += value;
    if(value) { truthyCount++; }}// good

  let array = [1.2.3];
  let num = 1;
  num += 1;
  num -= 1;

  const sum = array.reduce((a, b) = > a + b, 0);
  const truthyCount = array.filter(Boolean).length;
Copy the code
  • 13.7 avoid=Newline before/after. If your statement exceedsmax-lenAnd then use(a)Wrap the value before wrapping it. eslintoperator-linebreak.
// bad
const foo =
  superLongLongLongLongLongLongLongLongFunctionName();

// bad
const foo
  = 'superLongLongLongLongLongLongLongLongString';

// good
const foo = (
  superLongLongLongLongLongLongLongLongFunctionName()
);

// good
const foo = 'superLongLongLongLongLongLongLongLongString';
Copy the code
  • 13.8 Unused variables are not allowed. eslint: no-unused-vars
// bad

var some_unused_var = 42;

// The definition is not used
var y = 10;
y = 5;

// Reads used to modify themselves are not considered used
var z = 0;
z = z + 1;

// The parameter is defined but not used
function getX(x, y) {
    return x;
}

// good
function getXPlusY(x, y) {
  return x + y;
}

var x = 1;
var y = a + 2;

alert(getXPlusY(x, y));

// 'type' can be ignored even if it is not used, because this has a rest value attribute.
// This is a form of extracting an object from an object that ignores a particular field
var{ type, ... coords } = data;// 'coords' is now a' data' object with no 'type' attribute
Copy the code

ascension

  • 14.1 The VAR declaration is upgraded. Const and LET declarations are given a new concept called Temporal Dead Zones (TDZ). It is important to know why Typeof is no longer secure.

function example() {
  console.log(notDefined); // => throws a ReferenceError
}

// If used before a variable declaration, the output is normal because the variable declaration is promoted and the value is not.
function example() {
  console.log(declaredButNotAssigned); // => undefined
  var declaredButNotAssigned = true;
}

// same as above
function example() {
  let declaredButNotAssigned;
  console.log(declaredButNotAssigned); // => undefined
  declaredButNotAssigned = true;
}

// with const, let is not promoted
function example() {
  console.log(declaredButNotAssigned); // => throws a ReferenceError
  console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
  const declaredButNotAssigned = true;
}
Copy the code
  • 14.2 Anonymous function expressions andvarIs the same
function example() {
  console.log(anonymous); // => undefined

  anonymous(); // => TypeError anonymous is not a function

  var anonymous = function () {
    console.log('anonymous function expression');
  };
}
Copy the code
  • 14.3 A named function expression promotes its variable name, not the function name or body
function example() {
  console.log(named); // => undefined

  named(); // => TypeError named is not a function

  superPower(); // => ReferenceError superPower is not defined

  var named = function superPower() {
    console.log('Flying');
  };
}

// The function name is the same as the variable name
function example() {
  console.log(named); // => undefined

  named(); // => TypeError named is not a function

  var named = function named() {
    console.log('named');
  };
}
Copy the code
  • 14.4 Function declarations promote function names and function bodies
function example() {
  superPower(); // => Flying

  function superPower() {
    console.log('Flying'); }}Copy the code
  • For more information go to JavaScript Scoping & Collieries by Ben Cherry.

Comparison and equality

  • 15.1 Using === and! == instead of == and! =. eslint: eqeqeq

  • 15.2 Conditional statements such as if use the forced ToBoolean abstraction method to evaluate their expressions and always follow these simple rules:

  • Objects => true

  • Undefined => false

  • Null => false

  • Booleans => the value of the boolean

  • Numbers

    • +0, -0, or NaN => false
    • Other = > true
  • Strings

    • ' '= >false
    • Other = > true
if ([0] && []) {
  // true
  // Arrays (even empty arrays) are objects that evaluate to true
}
Copy the code
  • 15.3 Boolean comparisons can be omitted, but strings and numbers are displayed for comparison
// bad
if (isValid === true) {
  // ...
}

// good
if (isValid) {
  // ...
}

// bad
if (name) {
  // ...
}

// good
if(name ! = =' ') {
  // ...
}

// bad
if (collection.length) {
  // ...
}

// good
if (collection.length > 0) {
  // ...
}
Copy the code
  • 15.4 switch case, in thecasedefaultUse curly braces to create a block in a clause.let.const.function, and class). eslint rules: no-case-declarations.

Lexical declarations are visible throughout the switch block, but are initialized only when assigned, which only happens when case is reached. Problems arise when multiple case clauses try to define the same thing.

// bad
switch (foo) {
  case 1:
    let x = 1;
    break;
  case 2:
    const y = 2;
    break;
  case 3:
    function f() {
      // ...
    }
    break;
  default:
    class C {}}// good
switch (foo) {
  case 1: {
    let x = 1;
    break;
  }
  case 2: {
    const y = 2;
    break;
  }
  case 3: {
    function f() {
      // ...
    }
    break;
  }
  case 4:
    bar();
    break;
  default: {
    class C {}}}Copy the code
  • 15.5 Ternary expressions should not be nested and are usually single-line expressions.

eslint rules: no-nested-ternary.

// bad
const foo = maybe1 > maybe2
  ? "bar"
  : value1 > value2 ? "baz" : null;

// better
const maybeNull = value1 > value2 ? 'baz' : null;

const foo = maybe1 > maybe2
  ? 'bar'
  : maybeNull;

// best
const maybeNull = value1 > value2 ? 'baz' : null;

const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
Copy the code
  • 15.7 Avoid unnecessary ternary expressions

eslint rules: no-unneeded-ternary.

// bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;

// good
const foo = a || b;
constbar = !! c;constbaz = ! c;Copy the code
  • 15.8 When mixing operators, use the(a)Only if they are standard arithmetic operators (+.-.*, & /), and don’t use them when their priority is obvious. eslint:no-mixed-operators
// bad
const foo = a && b < 0 || c > 0 || d + 1= = =0;

// bad
const bar = a ** b - 5 % d;

// bad
if (a || b && c) {
  return d;
}

// good
const foo = (a && b < 0) || c > 0 || (d + 1= = =0);

// good
const bar = (a ** b) - (5 % d);

// good
if (a || (b && c)) {
  return d;
}

// good
const bar = a + b / c * d;
Copy the code

block

  • 16.1 Use curly braces{}Wrap multi-line code blocks. eslint:nonblock-statement-body-position
// bad
if (test)
  return false;

// good
if (test) return false;

// good
if (test) {
  return false;
}

// bad
function foo() { return false; }

// good
function bar() {
  return false;
}
Copy the code
  • 16.2 elseifKeep the curly braces on one line. eslint:brace-style
// bad
if (test) {
  thing1();
  thing2();
}
else {
  thing3();
}

// good
if (test) {
  thing1();
  thing2();
} else {
  thing3();
}
Copy the code
  • 16.3 ififUse both statementsreturnGo back to the backelseI don’t have to write it. ififBlock containsreturnThe one behind itelse ifBlock also containsreturnIt can be done at this timeelse ifOpen it. eslint:no-else-return
// bad
function foo() {
  if (x) {
    return x;
  } else {
    returny; }}// bad
function cats() {
  if (x) {
    return x;
  } else if (y) {
    returny; }}// bad
function dogs() {
  if (x) {
    return x;
  } else {
    if (y) {
      returny; }}}// good
function foo() {
  if (x) {
    return x;
  }

  return y;
}

// good
function cats() {
  if (x) {
    return x;
  }

  if (y) {
    returny; }}// good
function dogs(x) {
  if (x) {
    if (z) {
      returny; }}else {
    returnz; }}Copy the code

control

  • 17.1 When you control statementsif.whileWhen the length is too long or exceeds the maximum length limit, place each criterion on a separate line with the logical operator at the beginning of the line.
// bad
if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
  thing1();
}

// bad
if (foo === 123 &&
  bar === 'abc') {
  thing1();
}

// bad
if (foo === 123
  && bar === 'abc') {
  thing1();
}

// bad
if (
  foo === 123 &&
  bar === 'abc'
) {
  thing1();
}

// good
if (
  foo === 123
  && bar === 'abc'
) {
  thing1();
}

// good
if (
  (foo === 123 || bar === 'abc')
  && doesItLookGoodWhenItBecomesThatLong()
  && isThisReallyHappening()
) {
  thing1();
}

// good
if (foo === 123 && bar === 'abc') {
  thing1();
}
Copy the code
  • 17.2 Do not replace control statements with selection operators.
// bad! isRunning && startRunning();// good
if(! isRunning) { startRunning(); }Copy the code

annotation

  • 18.1 Multi-line comments/ * *... * /
// bad
// make() returns a new element
// based on the passed in tag name
//
// @param {String} tag
// @return {Element} element
function make(tag) {

  // ...

  return element;
}

// good
/** * make() returns a new element * based on the passed-in tag name */
function make(tag) {

  // ...

  return element;
}
Copy the code
  • 18.2 Single-line comment//, place a single line comment above the commented area. If the comment is not on the first line, precede it with an empty line
// bad
const active = true;  // is current tab

// good
// is current tab
const active = true;

// bad
function getType() {
  console.log('fetching type... ');
  // set the default type to 'no type'
  const type = this._type || 'no type';

  return type;
}

// good
function getType() {
  console.log('fetching type... ');

  // set the default type to 'no type'
  const type = this._type || 'no type';

  return type;
}

// also good
function getType() {
  // set the default type to 'no type'
  const type = this._type || 'no type';

  return type;
}
Copy the code
  • 18.3 Add a space at the beginning of all comments for easy reading. eslint: spaced-comment
// bad
//is current tab
const active = true;

// good
// is current tab
const active = true;

// bad
/** *make() returns a new element *based on the passed-in tag name */
function make(tag) {

  // ...

  return element;
}

// good
/** * make() returns a new element * based on the passed-in tag name */
function make(tag) {

  // ...

  return element;
}
Copy the code
  • 18.4 Add before the commentFIXME 'orThe TODO ‘prefix, which helps other developers quickly understand the problem you point out or the solution to the problem you suggest.
class Calculator extends Abacus {
  constructor() {
    super(a);// FIXME: shouldn't use a global here
    total = 0; }}Copy the code
class Calculator extends Abacus {
  constructor() {
    super(a);// TODO: total should be configurable by an options param
    this.total = 0; }}Copy the code

The blank space

  • 19.1 Tab use two Spaces (or four, as happy as you are, but team unity is a must). eslint: indent
// bad
function foo() {,,,,const name;
}

// bad
function bar() {,const name;
}

// good
function baz() {,,const name;
}
Copy the code
  • 19.2 in braces{}One space ahead. eslint:space-before-blocks
// bad
function test(){
  console.log('test');
}

// good
function test() {
  console.log('test');
}

// bad
dog.set('attr', {age: '1 year'.breed: 'Bernese Mountain Dog'});// good
dog.set('attr', {
  age: '1 year'.breed: 'Bernese Mountain Dog'});Copy the code
  • 19.3 In Control Statementsif.whileLeave one space before the parentheses of. In function calls and definitions, there is no space between the function name and the parentheses. eslint:keyword-spacing
// bad
if(isJedi) {
  fight ();
}

// good
if (isJedi) {
  fight();
}

// bad
function fight () {
  console.log ('Swooosh! ');
}

// good
function fight() {
  console.log('Swooosh! ');
}
Copy the code
  • 19.4 Separate operators with Spaces. eslint: space-infix-ops
// bad
const x=y+5;

// good
const x = y + 5;
Copy the code
  • 19.5 An Empty Line at the End of the File ESLint: eol-last
// bad
import { es6 } from './AirbnbStyleGuide';
  // ...
export default es6;
Copy the code
// bad
import { es6 } from './AirbnbStyleGuide';
  // ...
export defaultes6; ↵ ↵Copy the code
// good
import { es6 } from './AirbnbStyleGuide';
  // ...
export defaultes6; ↵Copy the code
  • 19.6 Newline when long method chains (typically more than two) occur. Starting with a dot emphasizes that the line is a method call, not a new statement. eslint: newline-per-chained-call no-whitespace-before-property
// bad
$('#items').find('.selected').highlight().end().find('.open').updateCount();

// bad
$('#items').
  find('.selected').
    highlight().
    end().
  find('.open').
    updateCount();

// good
$('#items')
  .find('.selected')
    .highlight()
    .end()
  .find('.open')
    .updateCount();

// bad
const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led'.true)
    .attr('width', (radius + margin) * 2).append('svg:g')
    .attr('transform'.`translate(${radius + margin}.${radius + margin}) `)
    .call(tron.led);

// good
const leds = stage.selectAll('.led')
    .data(data)
  .enter().append('svg:svg')
    .classed('led'.true)
    .attr('width', (radius + margin) * 2)
  .append('svg:g')
    .attr('transform'.`translate(${radius + margin}.${radius + margin}) `)
    .call(tron.led);

// good
const leds = stage.selectAll('.led').data(data);
Copy the code
  • 19.7 After a code block, a blank line precedes the next statement.
// bad
if (foo) {
  return bar;
}
return baz;

// good
if (foo) {
  return bar;
}

return baz;

// bad
const obj = {
  foo() {
  },
  bar() {
  },
};
return obj;

// good
const obj = {
  foo() {
  },

  bar() {
  },
};

return obj;

// bad
const arr = [
  function foo() {},function bar() {},];return arr;

// good
const arr = [
  function foo() {},function bar() {},];return arr;
Copy the code
  • 19.8 Do not intentionally leave unnecessary blank lines. eslint: padded-blocks
// bad
function bar() {

  console.log(foo);

}

// also bad
if (baz) {

  console.log(qux);
} else {
  console.log(foo);

}

// good
function bar() {
  console.log(foo);
}

// good
if (baz) {
  console.log(qux);
} else {
  console.log(foo);
}
Copy the code
  • 19.9 Do not put Spaces in parentheses. eslint: space-in-parens
// bad
function bar( foo ) {
  return foo;
}

// good
function bar(foo) {
  return foo;
}

// bad
if ( foo ) {
  console.log(foo);
}

// good
if (foo) {
  console.log(foo);
}
Copy the code
  • 19.10 Do not put Spaces in square brackets. See the sample. eslint: array-bracket-spacing
// bad
const foo = [ 1.2.3 ];
console.log(foo[ 0 ]);

// good, place a space after the comma
const foo = [1.2.3];
console.log(foo[0]);
Copy the code
  • 19.11 curly braces{}Add Spaces. eslint:object-curly-spacing
// bad
const foo = {clark: 'kent'};

// good
const foo = { clark: 'kent' };


// bad
function foo() {return true; }if (foo) { bar = 0; }// good
function foo() { return true; }
if (foo) { bar = 0; }
Copy the code
  • 19.12 Avoid a line of code with more than 100 characters (including Spaces, and do not wrap pure strings).
// bad
const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy;

// bad
$.ajax({ method: 'POST'.url: 'https://airbnb.com/'.data: { name: 'John' } }).done((a)= > console.log('Congratulations! ')).fail((a)= > console.log('You have failed this city.'));

// good
const foo = jsonData
  && jsonData.foo
  && jsonData.foo.bar
  && jsonData.foo.bar.baz
  && jsonData.foo.bar.baz.quux
  && jsonData.foo.bar.baz.quux.xyzzy;

// good
$.ajax({
  method: 'POST'.url: 'https://airbnb.com/'.data: { name: 'John' },
})
  .done((a)= > console.log('Congratulations! '))
  .fail((a)= > console.log('You have failed this city.'));
Copy the code
  • 19.13 .Avoid Spaces before,.Need space after. eslint:comma-spacing
// bad
var foo = 1,bar = 2;
var arr = [1 , 2];

// good
var foo = 1, bar = 2;
var arr = [1.2];
Copy the code
  • 19.14 In the properties of an object, Spaces must be placed between key values. eslint: key-spacing
// bad
var obj = { "foo" : 42 };
var obj2 = { "foo":42 };

// good
var obj = { "foo": 42 };
Copy the code
  • 19.15 No Spaces at the end of the line. eslint: no-trailing-spaces

  • 19.16 Avoid multiple blank lines. Only one blank line is allowed at the end of the file. eslint: no-multiple-empty-lines

// bad
var x = 1;

var y = 2;

// good
var x = 1;

var y = 2;
Copy the code

The comma

  • 20.1 Do not start with commas. eslint: comma-style
// bad
const story = [
    once
  , upon
  , aTime
];

// good
const story = [
  once,
  upon,
  aTime,
];

// bad
const hero = {
    firstName: 'Ada'
  , lastName: 'Lovelace'
  , birthYear: 1815
  , superPower: 'computers'
};

// good
const hero = {
  firstName: 'Ada'.lastName: 'Lovelace'.birthYear: 1815.superPower: 'computers'};Copy the code
  • 20.2 Add an extra comma at the end, depending on what the team is used to
// git diff const hero = {firstName: 'Florence',- lastName: 'Nightingale'
+ lastName: 'Nightingale',
+ inventorOf: ['coxcomb chart', 'modern nursing']}; // git diff const hero = {firstName: 'Florence', lastName: 'Nightingale',+ inventorOf: ['coxcomb chart', 'modern nursing'],
};
Copy the code
// bad
const hero = {
  firstName: 'Dana'.lastName: 'Scully'
};

const heroes = [
  'Batman'.'Superman'
];

// good
const hero = {
  firstName: 'Dana'.lastName: 'Scully'};const heroes = [
  'Batman'.'Superman',];// bad
function createHero(firstName, lastName, inventorOf) {
  // does nothing
}

// good
function createHero(firstName, lastName, inventorOf,) {
  // does nothing
}

// good (note that a comma must not appear after a "rest" element)
function createHero(firstName, lastName, inventorOf, ... heroArgs) {
  // does nothing
}

// bad
createHero(
  firstName,
  lastName,
  inventorOf
);

// good
createHero(
  firstName,
  lastName,
  inventorOf,
);

// good (note that a comma must not appear after a "rest" element)createHero( firstName, lastName, inventorOf, ... heroArgs )Copy the code

A semicolon

  • 21.1 When JavaScript encountered a Semicolon without a Semicolon, it used the Automatic Semicolon Insertion rule to determine whether to add a Semicolon at the end of the line. However, ASI contains some wacky behavior, and if JavaScript gets your newline wrong, your code will break. So using a semicolon explicitly reduces that uncertainty.
// bad
(function () {
  const name = 'Skywalker'
  return name
})()

// good
(function () {
  const name = 'Skywalker';
  returnname; } ());// good
;(() = > {
  const name = 'Skywalker';
  returnname; } ());Copy the code

More and more.

type

  • 22.1 Perform a cast at the beginning of a declaration.

  • 22.2 the String eslint: no – new – wrappers

// => this.reviewScore = 9;

// bad
const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"

// bad
const totalScore = this.reviewScore + ' '; // invokes this.reviewScore.valueOf()

// bad
const totalScore = this.reviewScore.toString(); // Mandatory string Not guaranteed

// good
const totalScore = String(this.reviewScore);
Copy the code
  • 22.3 Number eslint: radix
const inputValue = '4';

// bad
const val = new Number(inputValue);

// bad
const val = +inputValue;

// bad
const val = inputValue >> 0;

// bad
const val = parseInt(inputValue);

// good
const val = Number(inputValue);

// good
const val = parseInt(inputValue, 10);
Copy the code
  • 22.4 Please explain in the comments why the shift operation is used, whatever you are doing, e.g., due toparseIntIt’s your performance bottleneck that makes you have to use the shift operation. Please explain this becausePerformance reasons.
// good
/** * parseInt causes code to run slowly * bitrat The String forces it to a number to make it much faster. * /
const val = inputValue >> 0;
Copy the code
  • 22.5 Note: Be careful when operating with bitshift. Numbers are represented as 64-bit values, but the bitshift operation always returns a 32-bit integer. For integer values greater than 32 bits, Bitshift can cause unexpected behavior.
2147483647 >> 0 / / = > 2147483647
2147483648 >> 0 / / = > - 2147483648
2147483649 >> 0 / / = > - 2147483647
Copy the code
  • 22.6 Booleans
const age = 0;

// bad
const hasAge = new Boolean(age);

// good
const hasAge = Boolean(age);

// best
consthasAge = !! age;Copy the code

Naming conventions

  • 23.1 Avoid naming with one letter and make your naming more semantic. eslint: id-length
// bad
function q() {
  // ...
}

// good
function query() {
  // ...
}
Copy the code
  • 23.2 Name your objects, functions, and instances with camelCase. eslint: camelcase
// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}

// good
const thisIsMyObject = {};
function thisIsMyFunction() {}
Copy the code
  • 23.3 Naming classes with PascalCase. eslint: new-cap
// bad
function user(options) {
  this.name = options.name;
}

const bad = new user({
  name: 'nope'});// good
class User {
  constructor(options) {
    this.name = options.name; }}const good = new User({
  name: 'yup'});Copy the code
  • 23.4 Do not use leading or trailing underscores. eslint: no-underscore-dangle

JavaScript has no concept of private properties or methods. Although the leading underline usually means “private” in concept, in reality, these attributes are completely public and therefore part of your API as well. This concept can lead developers to believe that changing this will not cause a crash or require no testing.

// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
this._firstName = 'Panda';

// good
this.firstName = 'Panda';
Copy the code
  • 23.5 Do not savethis“, using arrow functions or hard binding.
// bad
function foo() {
  const self = this;
  return function () {
    console.log(self);
  };
}

// bad
function foo() {
  const that = this;
  return function () {
    console.log(that);
  };
}

// good
function foo() {
  return (a)= > {
    console.log(this);
  };
}
Copy the code
  • 23.6 File names should be exported with default (export defaultThe names match exactly
// file 1 contents
class CheckBox {
  // ...
}
export default CheckBox;

// file 2 contents
export default function fortyTwo() { return 42; }

// file 3 contents
export default function insideDirectory() {}

// in some other file
// bad
import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename
import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export
import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export

// bad
import CheckBox from './check_box'; // PascalCase import/export, snake_case filename
import forty_two from './forty_two'; // snake_case import/filename, camelCase export
import inside_directory from './inside_directory'; // snake_case import, camelCase export
import index from './inside_directory/index'; // requiring the index file explicitly
import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly

// good
import CheckBox from './CheckBox'; // PascalCase export/import/filename
import fortyTwo from './fortyTwo'; // camelCase export/import/filename
import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index"
// ^ supports both insideDirectory.js and insideDirectory/index.js
Copy the code
  • 23.7 Default Export (export defaultWhen a function is used, the function name and file name must be the same.
function makeStyleGuide() {
  // ...
}

export default makeStyleGuide;
Copy the code
  • 23.8 Use PascalCase when you export a constructor/class/singleton/library object.
const AirbnbStyleGuide = {
  es6: {}};export default AirbnbStyleGuide;
Copy the code
  • 23.9 Abbreviations and acronyms should be all uppercase or all lowercase.

Names are for people, not computers.

// bad
import SmsContainer from './containers/SmsContainer';

// bad
const HttpRequests = [
  // ...
];

// good
import SMSContainer from './containers/SMSContainer';

// good
const HTTPRequests = [
  // ...
];

// best
import TextMessageContainer from './containers/TextMessageContainer';

// best
const Requests = [
  // ...
];
Copy the code
  • 23.10 All caps define constants for export
// bad
const PRIVATE_VARIABLE = 'should not be unnecessarily uppercased within a file';

// bad
export const THING_TO_BE_CHANGED = 'should obviously not be uppercased';

// bad
export let REASSIGNABLE_VARIABLE = 'do not use let with uppercase variables';

// ---

// allowed but does not supply semantic value
export const apiKey = 'SOMEKEY';

// better in most cases
export const API_KEY = 'SOMEKEY';

// ---

// bad - unnecessarily uppercases key while adding no semantic value
export const MAPPING = {
  KEY: 'value'
};

// good
export const MAPPING = {
  key: 'value'
};
Copy the code

accessor

  • 24.1 Accessor functions that do not use attributes.

  • 24.2 Do not use JavaScript getters/setters as they have side effects and are difficult to test, maintain, and understand. If necessary, you can build with getVal() and setVal().

// bad
class Dragon {
  get age() {
    // ...
  }

  set age(value) {
    // ...}}// good
class Dragon {
  getAge() {
    // ...
  }

  setAge(value) {
    // ...}}Copy the code
  • 24.3 If the property/method is oneboolean, please useisVal()hasVal().
// bad
if(! dragon.age()) {return false;
}

// good
if(! dragon.hasAge()) {return false;
}
Copy the code
  • 24.4 You can use get() and set(), but keep them the same.
class Jedi {
  constructor(options = {}) {
    const lightsaber = options.lightsaber || 'blue';
    this.set('lightsaber', lightsaber);
  }

  set(key, val) {
    this[key] = val;
  }

  get(key) {
    return this[key]; }}Copy the code

Events

  • 25.1 When passing data to events or others, you do not use raw values directly, but rather wrap them through objects. This allows you to add or subtract parameters in the future without having to find every processor in use.
// bad
$(this).trigger('listingUpdated', listing.id); . $(this).on('listingUpdated', (e, listingId) => {
  // do something with listingId
});
Copy the code

prefer:

// good
$(this).trigger('listingUpdated', { listingId: listing.id }); . $(this).on('listingUpdated', (e, data) => {
  // do something with data.listingId
});
Copy the code

summary

Specification is more about readability of code, after all, our code is more important for people to see. At the same time, a reasonable specification will also help us avoid many unnecessary bugs.

Communication group

Follow wechat official account: Front-end engine, reply: Add group.

Afterword.

If you see here, and this article is a little help to you, I hope you can move a small hand to support the author, thank 🍻. If there is something wrong in the article, we are welcome to point out and encourage each other. Thanks for reading. See you next time!

  • The article warehouse 🍹 🍰 fe – code
  • Social chat system (vue + Node + mongodb) – 💘🍦🙈Vchat

Interested students can pay attention to my public number front-end engine, fun and material.