Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
JavaScript Coding Style Guide.rst 30.69 KiB

JavaScript Coding Style Guide

Goal

Rules are not perfect. Prohibiting features that are useful in specific situations can have an impact on code implementation, but we set the rules for the benefit of most programmers. If we identify a rule cannot be followed in the operations, we should work together to improve the rule. You are supposed to have the basic JavaScript language capabilities to refer to this guide, instead of learning the JavaScript language from it.

General Principles

The code is required to be readable, maintainable, secure, reliable, testable, efficient, and portable on the premise that the functions are correct.

Convention

Rule: Conventions that must be complied with during programming Recommendation: Conventions that must be considered during programming

It is important to understand why this convention is so stated in both “Rules” or “Recommendations” and make efforts to comply.

Exceptions

If the General Principle is not violated, the rules can be properly violated after full consideration and sufficient reasons are provided. Exceptions compromise code consistency so please avoid exceptions. Exceptions to “Rules” should be rare.

The style consistency principle is preferred in the following situations: When modifying external open-source code and third-party code, comply with the existing rules of the open-source code and third-party code and keep the style consistent.

Programming Regulations

Naming Regulations

Rule 1.1 Use correct English spellings to name, no use of pinyin spellings.

Counterexample:xingming,zhanghao

Example:username,account

Rule 1.2 Use abbreviations as few as possible, except for common words or professional words. For example, context can be shortened to ctx, request can be shortened to req, and response can be shortened to resp.

Note: Complete spelling of words can avoid unnecessary misunderstanding.

Exceptions: The variable name of the cyclic condition can be i or j in the cyclic language.

Rule 1.3 Class name, enumeration name and namespace name should comply the upperCamelCase style.

Example:

// Class name
class User {
  constructor(username) {
    this.username = username;
  }

  sayHi() {
    console.log(`hi, ${this.username}`);
  }
}

// Enumeration name
const UserType = {
  TEACHER: 0,
  STUDENT: 1
};

// Namespace
const Base64Utils = {
  encrypt: function(text) {
    // todo encrypt
  },
  decrypt: function(text) {
    // todo decrypt
  }
};

Rule 1.4 Variable name, method name, and parameter name should comply the lowerCamelCase style.

Example:

let msg = 'Hello world';

function sendMsg(msg) {
  // todo send message
}

function findUser(userID) {
  // todo find user by user ID
}

Rule 1.5 The names of static constants and enumeration values must be in upper case, and words are separated by underscores (_).

Example:

const MAX_USER_SIZE = 10000;

const UserType = {
  TEACHER: 0,
  STUDENT: 1
};

Recommendation 1.6 Do not use negative Boolean variable names. Local variables or methods of the Boolean type must be prefixed with expressions with the meaning of right or wrong.

Counterexample:

let isNoError = true;
let isNotFound = false;
function empty() {}
function next() {}

Example:

let isError = false;
let isFound = true;
function isEmpty() {}
function hasNext() {}

Code Format

Rule 2.1 Use two spaces to indent, and do not use the tab character.

Note: Only spaces are allowed for indentation. Two spaces are allowed at a time. Tab characters are not allowed for indentation.

Example:

const dataSource = [
  {
    id: 1,
    title: 'Title 1',
    content: 'Content 1'
  },
  {
    id: 2,
    title: 'Title 2',
    content: 'Content 2'
  }
];

function render(container, dataSource) {
  if (!container || !dataSource || !dataSource.length) {
    return void 0;
  }

  const fragment = document.createDocumentFragment();
  for (let data of dataSource) {
    if (!data || !data.id || !data.title || !data.content) {
      continue;
    }
    const element = document.createElement("div");
    const textNode = document.createTextNode(`${data.title}: ${data.content}`);
    element.appendChild(textNode);
    element.setAttribute("id", data.id);
    fragment.appendChild(element);
  }
  container.appendChild(fragment);
}

Rule 2.2 The line width cannot exceed 120 characters.

Note: It is recommended that each line should contain no more than 120 characters. Use a proper method to break the line if the line contain more than 120 characters.

Exception: If a line of comments contains more than 120 characters of commands or URLs, keep it in one line for easy copying, pasting, and searching by running the grep command. The preprocessed error information is easy to read and understand in one line, even if it contains more than 120 characters.

Rule 2.3 The use of braces must comply with the following conventions:

  1. If the value in the braces is empty, the value can be abbreviated as {} without a newline.
  2. The left braces do not contain a line feed, and the left braces are followed by a line feed.
  3. Line feeds before the right brace. If there is else or catch after the brace, line feeds are not required. In other cases, line feeds are required.

Rule 2.4 Implementations of conditional and loop statements must be enclosed in braces, even if there is only one statement.

Counterexample:

if (condition)
  console.log('success');

for(let idx = 0; idx < 5; ++idx)
  console.log(idx);

Example:

if (condition) {
  console.log('success');
}

for(let idx = 0; idx < 5; ++idx) {
  console.log(idx);
}

Rule 2.5 Condition statements and loop statements cannot be written in one line.

Counterexample:

if (condition) { /* todo something */ } else { /* todo other */ }

let idx = 0;
while(idx < 10) console.log(idx);

Example:

if (condition) {
  /* todo something */
} else {
  /* todo other */
}

let idx = 0;
while(idx < 10) {
  console.log(idx);
}

Rule 2.6 The case and default in the switch statement must be indented by one layer.

Example:

switch(condition) {
  case 0:
    doSomething();
    break;
  case 1: { // the braces is not necessary
    doOtherthing();
    break;
  }
  default:
    break;
}

Rule 2.7 The line feeds of expressions must be consistent, and the operator must be placed at the end of the line.

Note: If a long expression does not meet the line width requirement, you need to wrap the line in a proper position. Generally, in the late phrase of the lower-priority operator or connector, the operator or connector should be placed at the end of the line. The operator and separator are placed at the end of the line, indicating that there is not the end.

Example:

// if the condition statement exceeds the line width.
if (userCount > MAX_USER_COUNT ||
  userCount < MIN_USER_COUNT) {
  doSomething();
}

const sum =
  number1 +
  number2 +
  number3 +
  number4 +
  number5 +
  number6 +
  number7 +
  number8 +
  number9;

Rule 2.8 Multiple variable definitions and assignment statements cannot be written in one line.

Counterexample:

let maxCount = 10, isCompleted = false;

let pointX, pointY;
pointX = 10; pointY = 0;

Example:

let maxCount = 10;
let isCompleted = false;

let pointX = 0;
let pointY = 0;

Rule 2.9 Spaces should highlight keywords and important information. Avoid unnecessary spaces.

Note: Spaces reduce code density and increase code readability. The general rules are as follows:

  1. Add a spaces after keywords ifelseifelseswitchwhilefor.
  2. No space is added between the parentheses.
  3. Spaces must be added on both sides of the braces, except for simple scenarios such as {}.
  4. No space is added between multiple parentheses.
  5. No space is added after unary operators (&, *, +, -, !,etc.).
  6. Add a space on the left and right side of binary operators =+-*/%|&||&&<><=>===!====!==, etc.)
  7. Add a space on the left and right side of ternary operator (?:).
  8. No space is added between the preceded or post-decrease (++, --) and variables.
  9. Add a space before a comma (,).
  10. Add a space after // in a single line.
  11. No space is added at the end of the line.

Rule 2.10 Expression statements must end with a semicolon.

Counterexample:

let username = 'jack'
let birthday = '1997-09-01'

console.log(`${username}'s birthday is ${birthday}`)

Example:

let username = 'jack';
let birthday = '1997-09-01';

console.log(`${username}'s birthday is ${birthday}`);

Recommendation 2.11 Use single quotation marks to wrap strings first.

Example:

let message = 'wolrd';
console.log(message);

Code instructions

Rule 3.1 When declaring a variable, use the keyword var, let, or const to prevent the variable from being exposed to the global scope.

Note: If the keyword var, let, or const is not used to declare a variable, the variable will be exposed to the global scope, which may overwrite the variable with the same name in the global scope. As a result, the GC cannot effectively reclaim the memory. In addition, when a variable contains sensitive information, exposuring to the global scope may result in information leakage. ** Use const instead of var for all references; Use let instead of var if you need a variable reference.** Because the scope of const and let is smaller, writing code is easier to control. Const ensures that the reference cannot be re-assigned. The pointer referenced by const is immutable, and an error will be reported during re-assignment, avoiding overwriting.

Counterexample:

function open() {
  url = 'http://127.0.0.1:8080'; //url will be exposed to the global scope
  //todo something
}
open();
console.log(url); //url can be accessed, output: http://127.0.0.1:8080

Example:

// ES5.1 Using var to declare variables
function open() {
  var url = 'http://127.0.0.1:8080';
  // todo something
}
open();
console.log(url); //Report: Uncaught ReferenceError: url is not defined
// In ES6, the let and const keywords are preferred to declare variables.
function open() {
  const url = 'http://127.0.0.1:8080';
  //todo something
}
open();
console.log(url); //Report: Uncaught ReferenceError: url is not defined

Rule 3.2 Function expressions must be used to declare functions in function blocks.

Note: Although many JS engines support in-block declaration functions, they do not belong to the ECMAScript specification. The poor implementation of browsers is incompatible with each other, and some are contrary to the future ECMAScript draft. In addition, ECMAScript5 does not support block scopes. All control flows are not independent scopes. Variables or functions declared in the control flows are in the scope of their parent functions or scripts. As a result, the declaration of functions or variables in blocks may be overwritten. If you do need to define a function in a block, you should initialize it using a function expression.

Counterexample:

function bar(name) {
  if (name === "hotel") {
    // 1. Define a foo function. The function scope is not the 'if' code block but the 'bar' function scope.
    function foo() {
      console.log("hotel foo A");
    }
  } else {
    // 2. Define the 'foo' function again to overwrite the 'foo' function definition under the 'if' condition branch.
    function foo() {
      console.log("hotel foo 2");
    }
  }
  foo && foo();
}
bar("hotel"); // output is shown as"hotel foo 2"

Example:

function bar(name) {
  var foo;
  if (name == "hotel") {
    foo = function () {
      console.log("hotel foo 1");
    };
  } else {
    foo = function () {
      console.log("hotel foo 2");
    }
  }
  foo && foo();
}
bar("hotel"); // Correct output"hotel foo 1"

Rule 3.3 Encapsulation of Basic Types is prohibited

Note: JavaScript has five basic data types: Undefined, Null, Boolean, Number, and String. The value of the base data type is unchangeable. The basic data type object used in JavaScript is only a value. It does not contain the methods and attributes of the object encapsulated by the object. When the attributes and methods are not required, the encapsulation type of the object does not need to be used.

Counterexample:

var isShow = new Boolean(false);
if (isShow) {
  alert('hi'); //It is executed, and the following information is displayed: hi
}

Example:

var isShow = false;
if (isShow) {
  alert('hi');
}

Rule 3.4 The use of with is prohibited

Note: Using ‘with’ makes your code semantically unclear, because objects of ‘with’ may conflict with local variables, changing the original meaning of the program.

Counterexample:

var foo = { x: 5 };
with(foo) {
  var x = 3;
  console.log(x); //Output: 5
}

Rule 3.5 this can only be used in object constructors, methods, and closures.

Note: In JavaScript, the “this” pointer represents the owner of the object that executes the current code. This has special semantics:

  • Global objects (in most cases)
  • Scope of the caller (when eval is used)
  • Nodes in the DOM tree (when adding event handling functions)
  • Newly created object (using a constructor)
  • Other objects (if the function is called() or apply())
var User = function(username) {
  this.username = username;
};
var user = new User('John');
console.log(user.username); // Output: John

var ClickCounter = {
  value: 0,
  click: function() {
    ++this.value;
  },
  getValue() {
    return this.value;
  }
};
console.log(Counter.getValue()); //Output: 0
Counter.click();
console.log(Counter.getValue()); //Output: 1

Rule 3.6 Do not use conditional comments in IE.

Note: Conditional compilation can be activated using the \@cc_on statement or the \@if or \@set statement in IE. Although comments can be made to be compatible with browsers other than IE, they hinder the execution of automation tools because they change the JavaScript syntax tree at run time.

Counterexample:

var f = function () {
  /*@cc_on @*/
  /*@if (@_jscript_version >= 4)
       alert("JavaScript version 4 or better");
    @else @*/
  alert("Conditional compilation not supported by this scripting engine.");
  /*@end @*/
};

Rule 3.7 Prototypes of built-in objects cannot be modified.

Note: As a set of public interfaces, built-in objects have conventional behaviors. Modifying the prototype may damage the interface semantics or cause abnormalities during debugging.

Counterexample:

Array.prototype.indexOf = function () { return -1 }
var arr = [1, 1, 1, 1, 1, 2, 1, 1, 1];
console.log(aar.indexOf(2)); // Output:-1

Rule 3.8 Do not directly use the built-in attribute of Object.prototype.

Note: ECMAScript 5.1 adds Object.create, which creates a new object and uses an existing object to provide the proto of the newly created object. Object.create(null) is a common pattern for creating objects used as maps. Unexpected behavior or vulnerability may occur when the object has an attribute with the same name as Object.prototype. For example, it is not safe for a web server to parse JSON input from a client and use hasOwnProperty to directly invoke the generated object, because a malicious client may send a similar JSON value ' {"hasOwnProperty": 1} ' and cause the server to crash.

Counterexample:

var hasBarProperty = foo.hasOwnProperty("bar");
var isPrototypeOfBar = foo.isPrototypeOf(bar);
var barIsEnumerable = foo.propertyIsEnumerable("bar");

Example: