Preface: Teams define code specifications based on THE ES6 and Eslint rules. The purpose of this article is to comb through and summarize the specifications that teams currently implement.

Author: Zheng Linghua, a member of the order second pay terminal team

directory

Eslint checks ES6 specification configurations

  1. Coding format specification
  2. Declarative uniqueness
  3. Initialize the definition specification
  4. Code writing considerations
  5. Derived class correlation

2. Airbnb standard excerpts

  1. Arrow function
  2. The constructor
  3. Iteration traversal
  4. Attribute definitions
  5. deconstruction
  6. function

3. Reference materials


Eslint checks ES6 specification configurations

1. Coding format specification

A. Specify whether to force curly braces for the arrow function. B. Specify whether to use brackets c for the arrow function parameters. Specifies the space before and after the arrow of the arrow function. D. the space e around the medium sign in the generator function. Specify Spaces between REST parameters and extension operators and their arguments f. Disallow curly braces in template literals from parentheses g. Enforces a space after * in yield expressions


A. Specify that the arrow function forces curly braces

//Eslint file configuration items
'arrow-body-style': ['error'.'as-needed', {
    requireReturnForObjectLiteral: false,}]Copy the code
parameter Parameters that note
as-needed When the braces are omitted, it is mandatory not to use them
requireReturnForObjectLiteral There is no need to explicitly return object literals Must be used with as-needed
// Examples of correct use in projects
// The braces can be omitted
let foo = (a)= > 0; 
// Do not return object literals explicitly
let foo = (a)= > ({ bar: 0 });

// Error comparison:
let foo = (a)= > {
    return ({bar: 0 });
};Copy the code

B. Specify whether to use parentheses for arrow function parameters

//Eslint file configuration items
'arrow-parens': ['error'.'as-needed', {
    requireForBlockBody: true,}]Copy the code
parameter Parameters that note
as-needed Omit parentheses when there is only one argument
requireForBlockBody When the body of a function is within an instruction block, the arguments must be enclosed in parentheses As needed. Quick judgment as to whether the function body is included in {}
// Project practice correct examples
// Only one parameter can be omitted
a.map(x= > {
  return x * x;
});
// To complement the requireForBlockBody parameter, change this code to
a.map((x) = > {
  return x * x;
});Copy the code

C. Space specification before and after the arrow of the arrow function

'arrow-spacing': ['error', { 
    before: true.after: true 
}]Copy the code
parameter Parameters that note
before There is space before the arrow
after There is space after the arrow
// Project application
a => a;Copy the code

The space around the * in the d.generator function

'generator-star-spacing': ['error', { 
    before: false.after: true 
}]Copy the code
parameter Parameters that note
before * there is no space before it
after * followed by a space
// Project correct use example
function* generator() {}Copy the code

E. Do not allow Spaces between rest parameters and extension operators and their parameters

'rest-spread-spacing': ['error'.'never']Copy the code
parameter Parameters that note
never There must be no space between the symbol and the parameter
/ / rest parameters
let [a, b, ...arr] = [1.2.3.4.5]
// The extension operator
function fn(){} fn(... args)Copy the code

F. Disallow curly braces in template literals from parentheses

'template-curly-spacing': 'error'Copy the code
// There are no parentheses inside curly braces
`hello, ${people.name}! `Copy the code

G. Enforces trailing Spaces in yield expressions

'yield-star-spacing': ['error'.'after']Copy the code
function* generator() {
  yield* other();
}Copy the code

2. Declare uniqueness

A. Do not modify variables declared by a class. B. Do not modify variables declared as const. Do not allow duplicate names in class members. D. Do not repeatedly introduce a module. E. Prohibit renaming with original names in import, export, or destruct assignments


A. Variables declared by the class cannot be modified

'no-class-assign': 'error'Copy the code
// In short, if class Name{} appears as object-type, then Name cannot be changed or assigned
// The following example is correct. Because A is just A variable all the way through
let A = class {
    b() {
        A = 0; 
        console.log(A); }}console.log(A); //class
let Foo = new A(); 
Foo.b(); / / 0
console.log(A); / / 0Copy the code

B. Disallow changes to const variables

'no-const-assign': 'error'Copy the code

C. Do not allow duplicate names in class members

'no-dupe-class-members': 'error'Copy the code

D. Do not re-introduce a module

'no-duplicate-imports': 'off'Copy the code
// Two variables introduced by the same module should be written in curly braces
import { merge, find } from 'module';Copy the code

E. Do not rename the same name as the original name in import, export, destruct assignment

'no-useless-rename': ['error', {
  ignoreDestructuring: false.ignoreImport: false.ignoreExport: false,}]Copy the code
// Forms such as {foo as foo} and {bar: bar} do not work as renaming, so redundant writing should be prohibited
import { foo as bar } from "baz";
export { foo as bar } from "foo";
let { [foo]: foo } = bar;Copy the code

3. Initialize the definition specification

A. form bol cannot be defined using the new keyword B. form bol to add a description language for debugging. C. Yield d must be used in the generator function. Use let or const instead of var e. Disallow declaring useless computed attributes f in literals. If the variable will not be assigned again, use const


The new keyword cannot be used for the type of A. sigma

'no-new-symbol': 'error'Copy the code
// Symbol should be called as a function
var foo = Symbol('foo');Copy the code

B. Add a description language when defining sembol to facilitate debugging

'symbol-description': 'error'Copy the code
let foo = Symbol("some description")Copy the code

C. The generator function must have a yield

'require-yield': 'error'Copy the code

D. Use let or const instead of var

'no-var': 'error'Copy the code

E. Disallow declaring useless computed attributes in literals

'no-useless-computed-key': 'error'Copy the code
// Useless ["a"] calculated attribute
var foo = {['0 + 1234'] :"b"};

/ / rewrite
var foo = { '0 + 1234': 0 };Copy the code

F. If the variable will not be assigned again, use const

'prefer-const': ['error', {
  destructuring: 'any'.ignoreReadBeforeAssign: true,}]Copy the code
parameter Parameters that note
destructuring When deconstructing assignments, all variables should be of the same type
ignoreReadBeforeAssign Ignore variables between declaration and first assignment So you can’t define and then assign
// When you deconstruct an assignment, either the values are const or both are lets
A0 is definite and B is not assigned
const {a: a0, b} = obj;
const a = a0 + 1;

// A and b are both variables, so let is used to deconstruct assignment definitions
let {a, b} = obj;
a = a + 1;
b = b + 1;

// Error example: when ignoreReadBeforeAssign=true, the initialize() function declaration between the timer declaration and assignment is omitted.
// This will cause an error at setInterval
let timer;
function initialize() {
    if (foo()) {
        clearInterval(timer);
    }
}
timer = setInterval(initialize, 100);

// Correct example, as long as the declaration is assigned!
const timer = setInterval(initialize, 100);
function initialize() {
    if(foo()) { clearInterval(timer); }}Copy the code

4. Matters needing attention in coding

A. Avoid confusing arrow functions with comparisons b. Use template literals instead of string concatenations c. Using the extension operator (…) D. Use rest arguments (… E. ParseInt () is not allowed to convert 2, 8, hexadecimal f. Requires an arrow function for callbacks. Syntax shorthand for g. Object literals


A. Avoid confusion between arrow functions and comparisons

'no-confusing-arrow': ['error', {
    allowParens: true,}]Copy the code
parameter Parameters that note
allowParens Relax the criteria to allow parentheses for arrow functions Return is not mandatory
// If strict mode is used, return is used to distinguish between an arrow function and a ternary comparison
var x = a= > { return 1 ? 2 : 3; };
var x = (a) = > { return 1 ? 2 : 3; };

// If allowParens=true, relax the criteria
var x = a= > (1 ? 2 : 3);
var x = (a) = > (1 ? 2 : 3);Copy the code

B. Use template literals instead of string concatenation

'prefer-template': 'error'Copy the code
let str = `Hello, ${name}! `Copy the code

C. Use the extension operator (…) Instead of.apply() calling mutable arguments

'prefer-spread': 'error'Copy the code
// Find the largest element in an array
Math.max.apply(null[14.3.77])
/ / equivalent
Math.max(... [14.3.77])
/ / equivalent
Math.max(14.3.77)Copy the code

D. Use rest parameters (… Variable name) instead of arguments

'prefer-rest-params': 'error'Copy the code
// The rest operator can provide a true array that explicitly represents parameters
// Arguments is an object that calls array methods
function foo(. args) {
    console.log(args);
}Copy the code

E. ParseInt () is not allowed to convert 2, 8, hexadecimal

'prefer-numeric-literals': 'error'Copy the code
// Only for 2, 8 hexadecimal values
// Convert numbers to other bases or convert variables using parseInt
0b111110111= = =503;
0o767= = =503;
0x1F7= = =503;

parseInt(1.3);
parseInt(foo, 2);Copy the code

F. The arrow function is required for the callback

'prefer-arrow-callback': ['error', {
  allowNamedFunctions: false.allowUnboundThis: true,}]Copy the code
parameter Parameters that note
allowNamedFunctions Error if there is a named function inside the callback
allowUnboundThis Instead of specifying this using bind(), the rule will dynamically flag the use of this
// Use this instead of bind(this)
// The callback function is anonymous
foo(function() { return this.a; });Copy the code

G. Shorthand for object literals

'object-shorthand': ['error'.'always', {
  ignoreConstructors: false.avoidQuotes: true,}]Copy the code
parameter Parameters that note
always Abbreviate if you can
ignoreConstructors Constructors cannot be omitted The first argument must be specified
avoidQuotes When the object key is a string, use the long format The first argument must be specified
// Since both keys of foo are strings, the following cannot be omitted
var foo = {
    "bar-baz": function() {},
    "qux": qux
}Copy the code

5. Derived class correlation

A. Constructor must call super B. Prohibit unnecessary constructors c. The derived function constructor disallows the use of this before super()


A. The constructor must call super

'constructor-super': 'error'Copy the code
// Derived class constructors must be called. Non-derived class constructors cannot call super().
class A {
    constructor() {}}class A extends B {
    constructor() {
        super();
    }
}Copy the code

B. Disallow unnecessary constructors

'no-useless-constructor': 'error'Copy the code
// The constructor must have the logical code to execute
class A {
    constructor() { doSomething(); }}// If there is no special logic, then the class returns null
class A {}Copy the code

C. The derived function constructor disallows the use of this before super()

'no-this-before-super': 'errorCopy the code
// If not, return a reference error.
class A extends B {
    constructor() {
        super(a);this.a = 0; // OK, this is after `super()`.}}Copy the code

2. Airbnb standard excerpts

1. Arrow function

  • When the function is particularly simple and has only one argument, omit braces, parentheses, and return
  • Improve the readability of chained calls by constantly passing this
  • However, return cannot be omitted when the result requires an object to be passed back

2. The constructor

  • Use class instead of Prototype
// Class is more concise
class Foo {
   constructor(){}
   getVal(){}  
}
/ / equivalent to the
Foo.prototype = {
   getVal(){}
}Copy the code
  • Using extends to implement inheritance does not directly manipulate Prototype
  • Class enables module development and enables chained calls by returning this
  • The data type of a class is a function, and the class itself points to the constructor
class Foo {}
typeof Foo;  // Function
Foo === Foo.prototype.constructor; //trueCopy the code

3. Iterate

  • The Iterator provided by ES6 is suitable for data structures with the Symbol. Iterator property deployed. Of traverses members
  • for… In traverses all enumerable objects, including the current object and the prototype
  • for… Of traverses a collection object and does not apply to all objects, depending on whether they have a [Symbol. Iterator] attribute. Only the current object is traversed
  • Airbnb recommends using higher-order functions such as map() and reduce() instead of for-of to facilitate function callbacks

4. Attribute definition

  • If the object has dynamic property names, use computable property names at the beginning to ensure that all properties are defined together
const obj = {
  id: 5.name: 'San Francisco',
  [getKey('enabled')]: true,}Copy the code

5. Deconstruction

  • It is recommended to use destruct assignments to reduce the introduction of temporary variables
  • When you need to return multiple values, use object destructuring instead of array destructuring so that order can be ignored when calling
// Array destruct => The order of the callback data is one to one
function processInput(input) {
  // then a miracle occurs
  return [left, right, top, bottom];
}
const [left, __, top] = processInput(input);

// Object destruct => Regardless of order, as long as the variable must have the same name as the property
function processInput(input) {
  // then a miracle occurs
  return { left, right, top, bottom };
}
const { left, right } = processInput(input);Copy the code
  • The internal mechanism of deconstruction assignment is to find the property of the same name and then assign to the corresponding variable. The latter is really assigned, not the former.
let { foo: baz } = { foo: "aaa".bar: "bbb" };
baz; // "aaa"
foo; // error: foo is not definedCopy the code

Function of 6.

  • Use function declarations instead of function expressions to facilitate identification on the call stack and avoid the whole function being promoted. Also, arrow functions can replace function expressions
  • Do not name arguments as arguments. This replaces the arguments object in the original function scope
  • Do not use arguments. With rest syntax… alternative
  • Recommendation: Function arguments should specify default values
// If the bad code is Boolean, it will even change the type of opTS
function handleThings(opts) {
   opts = opts || {};
}
//Airbnb recommended writing, initialization parameters
function handleThings(opts = {}) {}Copy the code

3. Reference materials

Airbnb JavaScript specification -ES6 In Depth -ES6 guide -ES6 In Depth