Front end code specification - JavaScript style guide

Front end code specification - JavaScript style guide

Based on github project [airbnb](https://github.com/airbnb/javascript "airbnb") translation also adds some personal understanding. The specification helps us better improve code readability and avoid some unnecessary bug s.
leleshuo

1. Object

1.1 create objects using literals eslint: no-new-object

// bad
const item = new Object();

// good
const item = {};

1.2 when creating an object with a dynamic attribute name, put all the defined attributes 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 property name
const obj = {
  id: 5,
  name: 'San Francisco',
  [getKey('enabled')]: true,
};

1.3 method abbreviation eslint: object-shorthand

// bad
const atom = {
  value: 1,

  addValue: function (value) {
    return atom.value + value;
  },
};

// good
const atom = {
  value: 1,

  // Object method
  addValue(value) {
    return atom.value + value;
  },
};

1.4 do not directly call object Methods on prototype, such as hasOwnProperty, propertyIsEnumerable, isPrototypeOf

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

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

// best
const has = Object.prototype.hasOwnProperty; // Make a cache within the function of the module
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
// ...
console.log(has.call(object, key));

1.5 for shallow copy of objects, the extension operator... Is more recommended than object assign. When deconstructing assignment to obtain several attributes specified by the object, it is recommended to use the rest operator, which is also

// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); 
delete copy.a; // so does this change the 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 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }

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

2. Array

2.1 assign values with literal values. eslint: no-array-constructor

// bad
const items = new Array();

// good
const items = [];

2.2 use the extension operator to make a shallow copy of the array, similar to the shallow copy of the 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];

2.3 the... Operator is recommended instead of array From to convert an array of classes into an array.

const foo = document.querySelectorAll('.foo');

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

// best
const nodes = [...foo];

3. Deconstruction

3.1 use the deconstruction assignment of the object to obtain and use one or more attribute values of the object. eslint: prefer-destructuring

// 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}`;
}

3.2 array deconstruction

const arr = [1, 2, 3, 4];

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

// good
const [first, second] = arr;

4. String

4.1 single quotation mark '' shall be used for string. eslint: quotes

// bad
const name = "Capt. Janeway";

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

// good
const name = 'Capt. Janeway';

4.2 + should not be used to connect newline strings.

// 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.';

4.3 use string template instead of + to splice strings. eslint: prefer-template template-curly-spacing

// 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}?`;
}

5. Functions

5.1 use named function expressions instead of function declarations. eslint: func-style

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

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

// good

const short = function longUniqueMoreDescriptiveLexicalFoo() {
  // ...
};

5.2 give priority to rest Syntax... Instead of arguments. eslint: prefer-rest-params

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

// good
function concatenateAll(...args) {
  return args.join('');
}

5.3 flexible use of

// 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]);

6. Semicolon

6.1 when JavaScript encounters a line break without a semicolon, it will use the rule of automatic semiconductor insertion to decide whether to add a semicolon at the end of the line. However, ASI contains some strange behavior. If JavaScript makes a mistake about your line feed, your code will break. Therefore, the explicit use of semicolons will reduce this uncertainty.

// bad
(function () {
  const name = 'Skywalker'
  return name
})()

// good
(function () {
  const name = 'Skywalker';
  return name;
}());

// good
;(() => {
  const name = 'Skywalker';
  return name;
}());

7. Naming convention

7.1 avoid naming with one letter and make your naming more semantic. eslint: id-length

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

// good
function query() {
  // ...
}

7.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() {}

7.3 name the class 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',
});

7.4 do not underline before or after. eslint: no-underscore-dangle

JavaScript has no concept of private properties or methods. Although the pre underline usually means "private" conceptually, in fact, these attributes are completely public, so this part is also the content of your API. This concept may lead developers to mistakenly believe that changing this will not cause a crash or do not require testing.

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

// good
this.firstName = 'Panda';

7.5 when exporting a function by default, the function name and file name are unified.

function makeStyleGuide() {
  // ...
}

export default makeStyleGuide;

7.6 when you export a constructor / class / singleton / function library object, use PascalCase.

const AirbnbStyleGuide = {
  es6: {
  }
};

export default AirbnbStyleGuide;

8. Notes

8.1 / * **/

// 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;
}

8.2 single line comments use / / to place single line comments above the annotated area. If the comment is not on the first line, add a blank line before the comment

// 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;
}

8.3 add a space at the beginning of all notes 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;
}

8.4 prefix the comments with FIXME 'or TODO', which helps other developers quickly understand the problems you pointed out or the solutions you suggested.

class Calculator extends Abacus {
  constructor() {
    super();

    // FIXME: shouldn't use a global here
    total = 0;
  }
}
class Calculator extends Abacus {
  constructor() {
    super();

    // TODO: total should be configurable by an options param
    this.total = 0;
  }
}
      --lele(Excellent code Porter)

Keywords: Javascript Code Style

Added by kerching on Sat, 22 Jan 2022 08:40:13 +0200