Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

ES6 programming style


May 08, 2021 ES6


Table of contents


1. Block-level scope

(1) let replaces var

ES6 presents commands for two new declaration let const Where, let completely replace var because the two semantics are the same, and let let side effects.

  1. 'use strict';
  2. if (true) {
  3. let x = 'hello';
  4. }
  5. for (let i = 0; i < 10; i++) {
  6. console.log(i);
  7. }

If the above code replaces let with var, it actually declares two global variables, which is obviously not the intention. Variables should only be valid within the block of code they declare, as the var command does not do.

The var command has a variable boost utility, and the let command does not have this problem.

  1. 'use strict';
  2. if (true) {
  3. console.log(x); // ReferenceError
  4. let x = 'hello';
  5. }

If the above code replaces let with var, console.log the line will not report an error, but will output undefined because the variable declaration is promoted to the head of the block. This violates the principle that variables are declared and then used.

Therefore, it is recommended that you no longer use the var command, but instead use the let command instead.

(2) Global constant and thread safety

Between let and const is recommended that const used first, especially in global environments, where variables should not be set, only constants should be set.

Const is better than let for several reasons. O ne is that const can remind the reader that this variable should not be changed; the other is that const is more in line with the functional programming idea, the operation does not change the value, only the new value, and this is also conducive to future distributed operations; and the last reason is that the JavaScript compiler optimizes the const, so use more const, which is conducive to improving the efficiency of the program, that is, the essential difference between let and const, In fact, the handling inside the compiler is different.

  1. // bad
  2. var a = 1, b = 2, c = 3;
  3. // good
  4. const a = 1;
  5. const b = 2;
  6. const c = 3;
  7. // best
  8. const [a, b, c] = [1, 2, 3];

Const declares that there are two other benefits to constants: that people who read the code immediately realize that this value should not be modified, and that they prevent errors caused by inadvertently modifying variable values.

All functions should be set to constant.

In the long run, JavaScript may have a multithreaded implementation (such as a project like Intel's River Trail), where let represents variables that should only appear in single-threaded code and not be multithreaded, which helps ensure thread safety.

2. String

Static strings use single or back quotes, not double quotes. Dynamic strings use back quotes.

  1. // bad
  2. const a = "foobar";
  3. const b = 'foo' + a + 'bar';
  4. // acceptable
  5. const c = foobar ;
  6. // good
  7. const a = 'foobar';
  8. const b = foo${a}bar ;

3. Deconstruct the assignment

Deconstructing assignments is preferred when assigning variables using array members.

  1. const arr = [1, 2, 3, 4];
  2. // bad
  3. const first = arr[0];
  4. const second = arr[1];
  5. // good
  6. const [first, second] = arr;

The arguments of the function, if they are members of an object, take precedence over deconstruction assignments.

  1. // bad
  2. function getFullName(user) {
  3. const firstName = user.firstName;
  4. const lastName = user.lastName;
  5. }
  6. // good
  7. function getFullName(obj) {
  8. const { firstName, lastName } = obj;
  9. }
  10. // best
  11. function getFullName({ firstName, lastName }) {
  12. }

If the function returns more than one value, the deconstruction assignment of the object is preferred over the deconstruction assignment of the array. This makes it easier to add return values later and change the order in which they are returned.

  1. // bad
  2. function processInput(input) {
  3. return [left, right, top, bottom];
  4. }
  5. // good
  6. function processInput(input) {
  7. return { left, right, top, bottom };
  8. }
  9. const { left, right } = processInput(input);

4. Object

A single-line defined object, and the last member does not end with a comma. A multi-line defined object, with the last member ending with a comma.

  1. // bad
  2. const a = { k1: v1, k2: v2, };
  3. const b = {
  4. k1: v1,
  5. k2: v2
  6. };
  7. // good
  8. const a = { k1: v1, k2: v2 };
  9. const b = {
  10. k1: v1,
  11. k2: v2,
  12. };

Objects are as static as possible, and once defined, no new properties can be added at will. If adding properties is unavoidable, use Object.assign method.

  1. // bad
  2. const a = {};
  3. a.x = 3;
  4. // if reshape unavoidable
  5. const a = {};
  6. Object.assign(a, { x: 3 });
  7. // good
  8. const a = { x: null };
  9. a.x = 3;

If the property name of an object is dynamic, you can define it using a property expression when you create an object.

  1. // bad
  2. const obj = {
  3. id: 5,
  4. name: 'San Francisco',
  5. };
  6. obj[getKey('enabled')] = true;
  7. // good
  8. const obj = {
  9. id: 5,
  10. name: 'San Francisco',
  11. [getKey('enabled')]: true,
  12. };

In the code above, the last property name of the object obj needs to be calculated. I t is a good idea to use a property expression that is defined with other properties when a new obj is created. That way, all the properties are defined in one place.

In addition, the properties and methods of the object, as far as possible, the use of concise expression, so that easy to describe and write.

  1. var ref = 'some value';
  2. // bad
  3. const atom = {
  4. ref: ref,
  5. value: 1,
  6. addValue: function (value) {
  7. return atom.value + value;
  8. },
  9. };
  10. // good
  11. const atom = {
  12. ref,
  13. value: 1,
  14. addValue(value) {
  15. return atom.value + value;
  16. },
  17. };

5. Array

Using the extension operator (... Copy the array.

  1. // bad
  2. const len = items.length;
  3. const itemsCopy = [];
  4. let i;
  5. for (i = 0; i < len; i++) {
  6. itemsCopy[i] = items[i];
  7. }
  8. // good
  9. const itemsCopy = [...items];

Use the Array.from method to convert array-like objects into arrays.

  1. const foo = document.querySelectorAll('.foo');
  2. const nodes = Array.from(foo);

6. Functions

Executing a function immediately can be written as an arrow function.

  1. (() => {
  2. console.log('Welcome to the Internet.');
  3. })();

For those cases where anonymous functions are used as arguments, try to replace them with arrow functions. Because it's more concise, and it's tied to this.

  1. // bad
  2. [1, 2, 3].map(function (x) {
  3. return x * x;
  4. });
  5. // good
  6. [1, 2, 3].map((x) => {
  7. return x * x;
  8. });
  9. // best
  10. [1, 2, 3].map(x => x * x);

The arrow function Function.prototype.bind and should no longer bind this _this/that.

  1. // bad
  2. const self = this;
  3. const boundMethod = function(...params) {
  4. return method.apply(self, params);
  5. }
  6. // acceptable
  7. const boundMethod = method.bind(this);
  8. // best
  9. const boundMethod = (...params) => method.apply(this, params);

Simple, single-line, reusable functions, with arrow functions recommended. If the function body is more complex and has more rows, the traditional function writing method should be used.

All configuration items should be concentrated in one object, placed in the last argument, and boolean values should not be used directly as parameters.

  1. // bad
  2. function divide(a, b, option = false ) {
  3. }
  4. // good
  5. function divide(a, b, { option = false } = {}) {
  6. }

Do not use the arguments variable in the body of the function, use the rest operator (... I nstead. Because the rest operator explicitly indicates that you want to get arguments, and arguments is an array-like object, the rest operator can provide a real array.

  1. // bad
  2. function concatenateAll() {
  3. const args = Array.prototype.slice.call(arguments);
  4. return args.join('');
  5. }
  6. // good
  7. function concatenateAll(...args) {
  8. return args.join('');
  9. }

Use the default syntax to set the default values for function parameters.

  1. // bad
  2. function handleThings(opts) {
  3. opts = opts || {};
  4. }
  5. // good
  6. function handleThings(opts = {}) {
  7. // ...
  8. }

7. Map structure

Note that objects and Maps are distinguished and are used only when simulating real-world entity objects. I f you just need key: value data structure, use the Map structure. Because Map has a built-in traversal mechanism.

  1. let map = new Map(arr);
  2. for (let key of map.keys()) {
  3. console.log(key);
  4. }
  5. for (let value of map.values()) {
  6. console.log(value);
  7. }
  8. for (let item of map.entries()) {
  9. console.log(item[0], item[1]);
  10. }

8. Class

Always replace the operation that requires prototype with Class. Because Class is written more concisely and more easily understood.

  1. // bad
  2. function Queue(contents = []) {
  3. this._queue = [...contents];
  4. }
  5. Queue.prototype.pop = function() {
  6. const value = this._queue[0];
  7. this._queue.splice(0, 1);
  8. return value;
  9. }
  10. // good
  11. class Queue {
  12. constructor(contents = []) {
  13. this._queue = [...contents];
  14. }
  15. pop() {
  16. const value = this._queue[0];
  17. this._queue.splice(0, 1);
  18. return value;
  19. }
  20. }

Inheritance extends using extends because it is simpler and there is no risk of instanceof operation.

  1. // bad
  2. const inherits = require('inherits');
  3. function PeekableQueue(contents) {
  4. Queue.apply(this, contents);
  5. }
  6. inherits(PeekableQueue, Queue);
  7. PeekableQueue.prototype.peek = function() {
  8. return this._queue[0];
  9. }
  10. // good
  11. class PeekableQueue extends Queue {
  12. peek() {
  13. return this._queue[0];
  14. }
  15. }

9. Modules

First, Module syntax is the standard way to write JavaScript modules, and you stick to it. Use import require

  1. // bad
  2. const moduleA = require('moduleA');
  3. const func1 = moduleA.func1;
  4. const func2 = moduleA.func2;
  5. // good
  6. import { func1, func2 } from 'moduleA';

Use export instead of module.exports.

  1. // commonJS的写法
  2. var React = require('react');
  3. var Breadcrumbs = React.createClass({
  4. render() {
  5. return <nav />;
  6. }
  7. });
  8. module.exports = Breadcrumbs;
  9. // ES6的写法
  10. import React from 'react';
  11. class Breadcrumbs extends React.Component {
  12. render() {
  13. return <nav />;
  14. }
  15. };
  16. export default Breadcrumbs;

If the module has only one output value, export default if the module has more than one output value, export default export default normal export do not export the same time.

Do not use wildcards in module inputs. Because this ensures that there is a default output (export default) in your module.

  1. // bad
  2. import * as myObject from './importModule';
  3. // good
  4. import myObject from './importModule';

If the module outputs a function by default, the initials of the function name should be lowercase.

  1. function makeStyleGuide() {
  2. }
  3. export default makeStyleGuide;

If the module outputs an object by default, the initials of the object name should be capitaled.

  1. const StyleGuide = {
  2. es6: {
  3. }
  4. };
  5. export default StyleGuide;

10. Use of ESLint

ESLint syntax rule and code style checking tool that can be used to ensure that code with correct syntax and uniform style is written.

First, install ESLint.

  1. $ npm i -g eslint

Then, install Airbnb syntax rules, as well as import, a11y, react plug-ins.

  1. $ npm i -g eslint-config-airbnb
  2. $ npm i -g eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react

Finally, create a new .eslintrc file at the root of the project and configure ESLint.

  1. {
  2. "extends": "eslint-config-airbnb"
  3. }

You can now check that the code for the current project conforms to preset rules.

The code .js index file is as follows.

  1. var unusued = 'I have no purpose!';
  2. function greet() {
  3. var message = 'Hello, World!';
  4. alert(message);
  5. }
  6. greet();

Checking this file with ESLint will report an error.

  1. $ eslint index.js
  2. index.js
  3. 1:1 error Unexpected var, use let or const instead no-var
  4. 1:5 error unusued is defined but never used no-unused-vars
  5. 4:5 error Expected indentation of 2 characters but found 4 indent
  6. 4:5 error Unexpected var, use let or const instead no-var
  7. 5:5 error Expected indentation of 2 characters but found 4 indent
  8. 5 problems (5 errors, 0 warnings)

The above code states that the original file has five errors, let two of which should not use the var command but let const