• Javascript 代码规范


    代码与风格

    空格与缩进

    switch 下的 case 和 default 必须增加一个缩进层级
    // good
    switch (variable) {
      case '1':
        // do...
        break;
      case '2':
        // do...
        break;
      default:
        // do...
    }
    
    // bad
    switch (variable) {
    case '1':
      // do...
      break;
    case '2':
      // do...
      break;
    default:
    // do...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    使用多行模板字符串时遵循缩进原则。当空行与空白字符敏感时,不使用多行模板字符串
    // good
    function foo() {
      let html = `
        

    `
    ; } // good function greeting(name) { return 'Hello, \n' + `${name.firstName} ${name.lastName}`; } // bad function greeting(name) { return `Hello, ${name.firstName} ${name.lastName}`; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    二元运算符两侧必须有一个空格,一元运算符与操作对象之间不允许有空格
    // good
    let a = !arr.length;
    a++;
    a = b + c;
    
    // bad
    let a =!arr.length;
    a ++;
    a = b+c;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    用作代码块起始的左花括号 { 前必须有一个空格
    // good
    if (condition) {
    }
    while (condition) {
    }
    function funcName() {
    }
    
    // bad
    if (condition){
    }
    while (condition){
    }
    function funcName(){
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    if / else / for / while / function / switch / do / try / catch / finally 关键字后,必须有一个空格
    // good
    if (condition) {
    }
    while (condition) {
    }
    (function () {
    })();
    
    // bad
    if(condition) {
    }
    while(condition) {
    }
    (function() {
    })();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    在对象创建时,属性中的 : 之后必须有空格,: 之前不允许有空格
    // good
    const obj = {
      a: 1,
      b: 2,
      c: 3,
    };
    
    // bad
    const obj = {
      a : 1,
      b:2,
      c :3,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    函数声明、具名函数表达式、函数调用中,函数名和 ( 之间不允许有空格
    // good
    function funcName() {
    }
    const funcName = function funcName() {
    };
    funcName();
    
    // bad
    function funcName () {
    }
    const funcName = function funcName () {
    };
    funcName ();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    , 和 ; 前不允许有空格。如果不位于行尾,, 和 ; 后必须跟一个空格
    // good
    callFunc(a, b);
    
    for (let i = 0; i < length; i++) {
      // xxx
    }
    
    // bad
    callFunc(a , b) ;
    
    for (let i = 0;i < length;i++) {
      // xxx
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    在函数调用、函数声明、单行声明的数组、括号表达式、属性访问、if / for / while / switch / catch 等语句中,() 和 [] 内紧贴括号部分不允许有空格
    // good
    callFunc(param1, param2, param3);
    const arr2 = [1, 2, 3];
    save(this.list[this.indexes[i]]);
    needIncream && (variable += increament);
    if (num > list.length) {
    }
    while (len--) {
    }
    
    // bad
    callFunc( param1, param2, param3 );
    const arr2 = [ 1, 2, 3 ];
    save( this.list[ this.indexes[ i ] ] );
    needIncreament && ( variable += increament );
    if ( num > list.length ) {
    }
    while ( len-- ) {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    generator 时,_ 前面不允许有空格,_ 后面必须有一个空格
    // good
    function* caller() {
      yield 'a';
      yield* callee();
      yield 'd';
    }
    
    // bad
    function * caller() {
      yield 'a';
      yield *callee();
      yield 'd';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    单行对象的大括号内侧要保留一个空格
    // good
    // simple object literals
    const obj = { foo: 'bar' };
    // nested object literals
    const obj = { foo: { zoo: 'bar' } };
    // destructuring assignment (EcmaScript 6)
    const { x, y } = y;
    // import/export declarations (EcmaScript 6)
    import { foo } from 'bar';
    export { foo };
    
    // bad
    // simple object literals
    const obj = {foo: 'bar'};
    // nested object literals
    const obj = {foo: { zoo: 'bar' }};
    // destructuring assignment (EcmaScript 6)
    const {x, y} = y;
    // import/export declarations (EcmaScript 6)
    import {foo} from 'bar';
    export {foo};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    换行

    每个独立语句结束后必须换行
    // good
    console.log('a');
    console.log('b');
    
    // bad
    console.log('a');console.log('b');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    运算符处换行时,运算符必须在上一行的行末
    // good
    if (user.isAuthenticated() &&
      user.isInRole('admin') &&
      user.hasAuthority('add-admin') ||
      user.hasAuthority('delete-admin')) {
      // Code
    }
    const result = number1 + number2 + number3 +
      number4 + number5;
    
    // bad
    if (user.isAuthenticated()
      && user.isInRole('admin')
      && user.hasAuthority('add-admin')
      || user.hasAuthority('delete-admin')) {
      // Code
    }
    const result = number1 + number2 + number3
      + number4 + number5;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    在函数声明、函数表达式、函数调用、对象创建、数组创建、for 语句等场景中,不允许在 , 或 ; 前换行
    // good
    const obj = {
      a: 1,
      b: 2,
      c: 3,
    };
    foo(
      aVeryVeryLongArgument,
      anotherVeryLongArgument,
      callback
    );
    
    // bad
    const obj = {
      a: 1
      , b: 2
      , c: 3
    };
    foo(
      aVeryVeryLongArgument
      , anotherVeryLongArgument
      , callback
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    
    
    • 1
    不同行为或逻辑的语句集,使用空行隔开,更易阅读
    // 仅为按逻辑换行的示例,不代表setStyle的最优实现
    function setStyle(element, property, value) {
      if (element == null) {
        return;
      }
    
      element.style[property] = value;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    解构多个变量或声明数组或对象时,如果变量数量超过 3 个或者单行字符超过 120 时,每个解构的变量必须单独一行
    // good
    const { name: personName, email: personEmail } = person;
    const {
      name: personName,
      email: personEmail,
      sex: personSex,
      age: personAge
    } = person;
    const person = { name: personName, email: personEmail };
    const person = {
      name: personName,
      email: personEmail,
      sex: personSex,
      age: personAge,
    };
    
    // bad
    const {name: personName, email: personEmail,
      sex: personSex, age: personAge
    } = person;
    const person = {name: personName, email: personEmail,
      sex: personSex, age: personAge};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    2.3.6 [强制] else 语句不允许换行
    // good
    if (xxx) {
    } else {
    }
    
    // bad 
    if (xxx) {
    }
    else {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    命名

    变量、函数、函数的 参数 使用 Camel 命名法
    const loadingModules = {};
    
    function stringFormat(source) {
    }
    
    function hear(theBells) {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    类使用 Pascal 命名法
    class Demo {
      text = 'this demo';
      appendTo() {
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    类的方法使用 Camel 命名法
    class TextNode( {
      cloneData() {
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    枚举变量 使用 Pascal 命名法,枚举的属性 使用 全部字母大写,单词间下划线分隔 的命名方式
    const TargetState = {
      READING: 1,
      READED: 2,
      APPLIED: 3,
      READY_TO_GO: 4,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    由多个单词组成的缩写词(如 HTTP),在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致
    // good
    function insertHTML(element, html) {
    }
    const httpRequest = new HTTPRequest();
    
    // bad
    function insertHtml(element, html) {
    }
    const httpRequest = new httpRequest();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    分号

    不得省略语句结束的分号
    // good
    const age = 10;
    export const age = 10;
    
    // bad
    const age = 10
    export const age = 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    函数定义结束不允许添加分号
    // good
    function funcName() {
    }
    export function funcName() {
    }
    // bad
    function funcName() {
    };
    export function funcName() {
    };
    
    // 如果是函数表达式,分号是不允许省略的。
    const funcName = function () {
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    类声明结束不允许添加分号
    // good
    class A {
    }
    
    // bad
    class A {
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    类成员定义中,方法定义后不允许添加分号,成员属性定义后必须添加分号
    // good
    class Foo {
      foo = 3;
      bar() {
      }
    }
    
    // bad
    class Foo {
      foo = 3
      bar() {
      };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    2.5.5 [强制] 属性装饰器后,可以不加分号的场景,不允许加分号
    // good
    class Foo {
      @log('INFO')
      bar() {
      }
      @log('INFO');
      ['bar' + 2]() {
      }
    }
    
    // bad
    class Foo {
      @log('INFO');
      bar() {
      }
      @log('INFO')
      ['bar' + 2]() {
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    括号

    IIFE 必须在函数表达式外添加 (,非 IIFE 不得在函数表达式外添加 (
    // good
    const task = (function () {
      // Code
      return result;
    })();
    const func = function () {
    };
    
    // bad
    const task = function () {
      // Code
      return result;
    }();
    const func = (function () {
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    箭头函数的参数只有一个,并且不包含解构时,参数部分的括号必须省略
    // good
    list.map(item => item * 2);
    // good
    const fetchName = async id => {
      const user = await request(`users/${id}`);
      return user.fullName;
    };
    
    // bad
    list.map((item) => item * 2);
    // bad
    const fetchName = async (id) => {
      const user = await request(`users/${id}`);
      return user.fullName;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    箭头函数的函数体只有一个单行表达式语句,且作为返回值时,省略 {} 和 return
    // good
    list.map(item => item * 2);
    const foo = () => (
      condition
        ? returnValueA()
        : returnValueB()
    );
    
    // bad
    list.map(item => {
      return item * 2;
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    箭头函数的函数体只有一个 Object Literal,且作为返回值时,使用 () 包裹
    // good
    list.map(item => ({ name: item[0], email: item[1] }));
    
    • 1
    • 2
    在 if / else / for / do / while 语句中,即使只有一行,也不得省略块 {…}
    // good
    if (condition) {
      callFunc();
    }
    if (condition) {
      return;
    }
    
    // bad
    if (condition) callFunc();
    if (condition) { callFunc(); }
    if (condition) { return; }
    if (condition) return;
    if (condition)
      callFunc();
      callFunc();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    注释

    优先使用 // 单行注释。// 后跟一个空格,缩进与下一行被注释说明的代码一致
    避免使用 /…/ 这样的多行注释,有多行注释内容时,使用多个单行注释
    为了便于代码阅读和自文档化,以下内容建议包含以 /*…/ 形式的块注释中
    • 文件
    • namespace
    • 函数或方法
    • 类属性
    • 事件
    • 全局变量
    • 常量
    • AMD 模块
    注释应该符合 JSDoc 的语法约定

    语言特性

    变量

    使用 let 和 const 定义变量,不使用 var
    // good
    for (let i = 0; i < 10; i++) {
    }
    
    // bad
    for (var i = 0; i < 10; i++) {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    变量、函数在使用前必须先定义
    // good
    const name = 'MyName';
    
    // bad
    name = 'MyName';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    声明并赋值时,每次只能声明一个变量;只声明不赋值时,允许一次声明多个变量。禁止使用保留字作为变量名,首次声明时禁止将 undefined 赋值给变量,禁止连续赋值
    // good
    const hangModules = [];
    const missModules = [];
    const visited = {};
    
    // bad 一次声明多个变量
    const hangModules = [],
      missModules = [],
      visited = {};
    // bad 使用保留字作为变量名
    const function = 'a';
    // bad 将`undefined`赋值给变量
    const a = undefined;
    // bad 连续赋值
    const a = b = c = 5;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    变量建议 即用即声明,不得在函数或其它形式的代码块起始位置统一声明所有变量
    // good
    function kv2List(source) {
      const list = [];
      for (let key in source) {
        if (source.hasOwnProperty(key)) {
          const item = {
            k: key,
            v: source[key],
          };
          list.push(item);
        }
      }
      const str = list.join('/');
      return { list, str };
    }
    
    // bad
    function kv2List(source) {
      const list = [];
      let key;
      let item;
      let str;
      for (key in source) {
        if (source.hasOwnProperty(key)) {
          item = {
            k: key,
            v: source[key],
          };
          list.push(item);
        }
      }
      str = list.join('/');
      return { list, str };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    解构

    不要使用 3 层及以上的解构
    // bad
    const { documentElement: { firstElementChild: { nextSibling } } } = window;
    
    • 1
    • 2
    使用解构减少中间变量
    // 下面交换变量的 demo 中,使用解构会牺牲一部分性能,但却获得了更简洁的代码,所以在非强性能场景下,我们推荐使用解构的方式。关于性能的影响,可以参考:这个链接
    
    // good
    [x, y] = [y, x];
    
    // bad
    let temp = x;
    x = y;
    y = temp;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    仅定义一个变量时不允许使用解构
    // good
    const len = myString.length;
    
    // bad
    const { length: len } = myString;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    如果不节省编写时产生的中间变量,解构表达式 = 号右边不允许是 ObjectLiteral 和 ArrayLiteral
    // good
    const { first: firstName, last: lastName } = person;
    const one = 1;
    const two = 2;
    
    // bad
    const [ one, two, three ] = [ 1, 2, 3 ];
    const { one, two } = { one: 1, two: 2 };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    使用剩余运算符时,剩余运算符之前的所有元素必需具名
    // good
    let [one, two, ...anyOther] = myArray;
    let other = myArray.slice(3);
    
    // bad
    let [,,, ...other] = myArray;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    条件

    在 Equality Expression 中使用类型严格的 ===
    // good
    if (age === 30) {
      // ......
    }
    
    // bad
    if (age == 30) {
      // ......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    当判断 null 或 undefined 时,允许使用 == null
    // good
    if (x == null) {
    }
    
    // bad
    if (x === null || x === undefined) {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    尽可能使用简洁的表达式
    // 字符串为空
    // good
    if (!name) {
      // ......
    }
    // bad
    if (name === '') {
      // ......
    }
    // 字符串非空
    // good
    if (name) {
      // ......
    }
    // bad
    if (name !== '') {
      // ......
    }
    // 数组非空
    // good
    if (collection.length) {
      // ......
    }
    // bad
    if (collection.length > 0) {
      // ......
    }
    // 布尔不成立
    // good
    if (!notTrue) {
      // ......
    }
    // bad
    if (notTrue === false) {
      // ......
    }
    // null 或 undefined
    // good
    if (noValue == null) {
      // ......
    }
    // bad
    if (noValue === null 
      || typeof noValue === 'undefined') {
      // ......
    }
    // 不要使用嵌套的三元表达式
    // bad
    if (a ? b : c ? d : e) {
      // ......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    通过条件判断的提前返回来避免多层嵌套的条件判断
    // good
    if (!expressionA) {
      return;
    }
    process(a);
    if (!expressionB) {
      return;
    }
    process(b);
    if (expressionC) {
      // do sth
    } else {
      // do sth
    }
    
    // bad
    if (expresssionA) {
      process(a);
      if (expressionB) {
        process(b);
        if (expressionC) {
          // do sth
        } else {
          // do sth
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    按执行频率排列分支的顺序
    if (condition === '执行频率最高') {
      // ...
    } else if (condition === '执行频率中等') {
      // ...
    } else if (condition === '执行频率最低') {
      // ...
    }
    
    switch (condition) {
      case '执行频率最高':
        // ...
        break;
      case '执行频率中等':
        // ...
        break;
      case '执行频率最低':
        // ...
        break;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    对于相同变量或表达式的多值条件,用 switch 代替 if
    switch (typeof variable) {
      case 'object':
        // ......
        break;
      case 'number':
      case 'boolean':
      case 'string':
        // ......
        break;
    }
    
    // bad
    const type = typeof variable;
    if (type === 'object') {
      // ......
    } else if (type === 'number' 
      || type === 'boolean' 
      || type === 'string') {
      // ......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    switch 语句
    • 每个 case 标签要么通过 break,return,throw 结束,要么通过注释直接跳过到下一标签。
    • 即使 default 标签中不包含逻辑,也不要省略。
    // good
    switch (input) {
      case 1:
      case 2:
        prepareOneOrTwo();
        // fall through
      case 3:
        handleOneTwoOrThree();
        break;
      default:
        handleLargeNumber(input);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    循环

    不要在循环体中包含函数表达式,事先将函数提取到循环体外
    // good
    function clicker() {
      // ......
    }
    for (let i = 0, len = elements.length; i < len; i++) {
      const element = elements[i];
      addListener(element, 'click', clicker);
    }
    
    // bad
    for (let i = 0, len = elements.length; i < len; i++) {
      const element = elements[i];
      addListener(element, 'click', function () {});
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    对循环内多次使用的不变值,在循环外用变量缓存
    // good
    const width = wrap.offsetWidth + 'px';
    for (let i = 0, len = elements.length; i < len; i++) {
      const element = elements[i];
      element.style.width = width;
      // ......
    }
    
    // bad
    for (let i = 0, len = elements.length; i < len; i++) {
      const element = elements[i];
      element.style.width = wrap.offsetWidth + 'px';
      // ......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    对有序集合进行遍历时,缓存 length
    // 正序遍历
    for (let i = 0, len = elements.length; i < len; i++) {
      const element = elements[i];
      // ......
    }
    // 逆序遍历
    let len = elements.length;
    while (len--) {
      const element = elements[len];
      // ......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    类型检测优先使用 typeof。对象类型检测使用 instanceof
    // string
    typeof variable === 'string'
    // number
    typeof variable === 'number'
    // boolean
    typeof variable === 'boolean'
    // Function
    typeof variable === 'function'
    // Object
    typeof variable === 'object'
    // RegExp
    variable instanceof RegExp
    // Array
    Array.isArray(variable)
    // null
    variable === null
    // null or undefined
    variable == null
    // undefined
    typeof variable === 'undefined'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    转换成 string 时,使用 String 方法
    // good
    const str = String(num);
    
    // bad
    const str = num + '';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    转换成 number 时,使用 Number 方法
    // good
    const number = Number(str);
    
    // bad
    const number = +str;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    string 转换成 number,要转换的字符串结尾包含非数字并期望忽略时,使用 parseInt,并且使用 parseInt 时,必须填写第二个参数来声明进制选项
    // good
    const width = '200px';
    parseInt(width, 10);
    
    // bad
    const width = '200px';
    parseInt(width);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    转换成 boolean 时,使用 Boolean 方法
    // good
    const isRed = Boolean(red);
    
    // bad
    const isRed = !!red;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    number 去除小数点,使用 Math.floor / Math.round / Math.ceil,不使用 parseInt
    // good
    const num = 3.14;
    Math.ceil(num);
    
    // bad
    const num = 3.14;
    parseInt(num, 10);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    表示小数时,不要省略整数位或者小数位,比如 .5
    // good
    const num1 = 0.5;
    const num2 = 2.0;
    const num3 = -0.7;
    
    // bad
    const num1 = .5;
    const num2 = 2.;
    const num3 = -.7;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    字符串

    字符串开头和结束使用单引号 ’
    const str = '我是一个字符串';
    const html = '
    拼接HTML可以省去双引号转义
    '
    ;
    • 1
    • 2
    使用字符串拼接的方式生成 HTML,需要根据语境进行合理的转义
    // HTML 转义
    const str = '

    ' + htmlEncode(content) + '

    '
    ; // HTML 转义 const str = '+ htmlEncode(value) + '">'; // URL 转义 const str = '+ htmlEncode(urlEncode(value)) + '">link'; // JavaScript字符串 转义 + HTML 转义 const str = '';
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    单行字符串的拼接或者字符串本身包含单引号建议使用字符串模板
    const str = `'name': ${name}`;
    
    • 1
    不要使用 \ 进行多行接续
    // good
    const longString = 'This is a very long string that far exceeds the 80 '
      + 'column limit. It does not contain long stretches of spaces since '
      + 'the concatenated strings are cleaner.';
    
    // bad
    const longString = 'This is a very long string that far exceeds the 80 \
      column limit. It unfortunately contains long stretches of spaces due \
      to how the continued lines are indented.';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    字符串内变量替换时,不要使用 2 层及以上的函数调用
    // good
    const fullName = getFullName(getFirstName(), getLastName());
    const s = `Hello ${fullName}`;
    
    // bad
    const s = `Hello ${getFullName(getFirstName(), getLastName())}`;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对象

    使用对象字面量 {} 创建新 Object
    // good
    const obj = {};
    
    // bad
    const obj = new Object();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    对象创建时,如果一个对象的 属性 可以不添加引号,建议该 属性 不添加引号
    // good
    const info = {
      name: 'someone',
      age: 28,
      'x-y': 20,
    };
    
    // bad
    const info = {
      'name': 'someone',
      'age': 28,
      'x-y': 20,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    对象属性后需要加结束的逗号
    // good
    const foo = {
      name: 'someone',
      age: 28,
    };
    const bar = { name: 'someone', age: 28 };
    
    // bad
    const foo = {
      name: 'someone',
      age: 28
    };
    const bar = { name: 'someone', age: 28, };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    不允许修改和扩展任何原生对象和宿主对象的原型
    // 以下行为绝对禁止
    String.prototype.trim = function () {
    };
    
    • 1
    • 2
    • 3
    属性访问时,尽量使用 .。对于不符合 Identifier 的命名的情况(如后端接口返回的数据),可以使用[expr]形式。
    info.age;
    info.more_info;
    info['more-info'];
    
    • 1
    • 2
    • 3
    定义对象时,如果键指向同名变量,需要进行缩写;能缩写的键需要写在不能缩写的键的前面
    // good
    const foo = {
      z,
      x: 1,
      y: 2,
    };
    // bad
    const foo = {
      x: 1,
      y: 2,
      z: z,
    };
    const bar = {
      x: 1,
      y: 2,
      z,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    定义方法时使用 MethodDefinition 语法,不使用 PropertyName: FunctionExpression 语法,不使用箭头函数语法
    // good
    const foo = {
      bar(x, y) {
        return x + y;
      }
    };
    const foo = {
      bar: hoc(function (x, y) {
        return x + y;
      })
    };
    
    // bad
    const foo = {
      bar: function (x, y) {
        return x + y;
      }
    };
    const foo = {
      bar: (x, y) => x + y
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    使用 Object.keys 或 Object.entries 进行对象遍历
    // good
    for (let key of Object.keys(foo)) {
      const value = foo[key];
    }
    
    // good
    for (const [key, value] of Object.entries(foo)) {
      // ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    尽量使用计算属性键在一个完整的字面量中完整地定义一个对象,避免对象定义后直接增加对象属性
    // good
    const MY_KEY = 'bar';
    const foo = {
      [MY_KEY + 'Hash']: 123
    };
    
    // bad
    const MY_KEY = 'bar';
    const foo = {};
    foo[MY_KEY + 'Hash'] = 123;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    避免直接调用 Object.prototype 上面的方法,例如 hasOwnProperty propertyIsEnumerable 以及 isPrototypeOf
    // good
    console.log(Object.prototype.hasOwnProperty.call(object, key));
    const has = Object.prototype.hasOwnProperty;
    console.log(has.call(object, key));
    
    // bad
    console.log(object.hasOwnProperty(key));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    进行对象浅拷贝时,使用 … 运算符。
    // good
    const obj = { ...oldObj };
    
    // bad
    const obj = Object.assign({}, oldObj);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    数组和集合

    使用数组字面量 [] 创建新数组。
    // good
    const arr = [];
    
    // bad
    const arr = new Array();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    进行数组浅拷贝时,使用 … 运算符。
    // good
    const arr = [ ...oldArr ];
    
    // bad
    const arr = Array.from(oldArr);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    不因为性能的原因自己实现数组排序功能,尽量使用数组的 sort 方法
    清空数组使用 .length = 0
    对数组进行连接操作时,使用数组展开语法
    // good
    foo = [...foo, newValue];
    bar = [...bar, ...newValues];
    
    // bad
    foo = foo.concat(newValue);
    bar = bar.concat(newValues);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    多行数组最后一个元素后面加逗号
    // good
    const foo = [
      'first value',
      'second value',
    ];
    const bar = [ 'first value', 'second value' ];
    
    // bad
    const foo = [
      'first value',
      'second value'
    ];
    const bar = [ 'first value', 'second value', ];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    数组遍历时,使用数组的原生方法以替代 for in 、 for of 用法
    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 使用最恰当的方法
    const sum = numbers.reduce((total, num) => total + num, 0);
    sum === 15;
    
    // 数组所有元素 +1
    // 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 使用最恰当的方法
    const increasedByOne = numbers.map(num => num + 1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    函数

    一个函数的长度控制在 50 行以内
    // bad
    function syncViewStateOnUserAction() {
      if (x.checked) {
        y.checked = true;
        z.value = '';
      } else {
        y.checked = false;
      }
      if (a.value) {
        warning.innerText = '';
        submitButton.disabled = false;
      } else {
        warning.innerText = 'Please enter it';
        submitButton.disabled = true;
      }
    }
    // good 直接阅读该函数会难以明确其主线逻辑,因此下方是一种更合理的表达方式:
    function syncViewStateOnUserAction() {
      syncXStateToView();
      checkAAvailability();
    }
    function syncXStateToView() {
      y.checked = x.checked;
      if (x.checked) {
        z.value = '';
      }
    }
    function checkAAvailability() {
      if (a.value) {
        clearWarnignForA();
      } else {
        displayWarningForAMissing();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    一个函数的参数控制在 6 个以内,且对于超宽的函数签名进行换行处理;超过六个参数的情况要把参数封装成对象传入
    // good
    function doSomething(firstname, lastname, age) {
      // …
    }
    function doSomething(
      veryLongArgumentOne,
      veryLongArgumentTwo,
      veryLongArgumentThree,
      veryLongArgumentFour) {
      // …
    }
    function doSomething(person) {
      // …
    }
    
    // bad
    function doSomething(firstname, lastname, age, veryLongArgumentOne, veryLongArgumentTwo, veryLongArgumentThree, veryLongArgumentFour) {
      // …
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    避免修改外部传入的参数对象
    // good    
    function info (person) {
      const thisInfo = {...person.info};
      thisInfo.xx = 'info';
      return thisInfo;
    }
    // bad    
    function info (person) {
      const thisInfo = person.info;
      thisInfo.xx = 'info';
      return thisInfo;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    使用变量默认语法代替基于条件判断的默认值声明
    // good
    function foo(text = 'hello') {
    }
    
    // bad
    function foo(text) {
      text = (typeof text !== 'undefined') ? text : 'hello';
    }
    function foo(text) {
      text = text || 'hello';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    不要使用 arguments 对象,应使用 …args 代替
    // good
    function foo(...args) {
      console.log(args.join(''));
    }
    
    // bad
    function foo() {
      console.log([].join.call(arguments));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    在适当的时候将闭包内大对象置为 null
    一个函数被设计为需要 call 和 apply 的时候,不能是箭头函数

    面向对象

    使用 class 关键字定义一个类
    // good
    class TextNode {
      constructor(value, engine) {
        this.value = value;
        this.engine = engine;
      }
      clone() {
        return this;
      }
    }
    // bad
    function TextNode(value, engine) {
      this.value = value;
      this.engine = engine;
    }
    TextNode.prototype.clone = function () {
      return this;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    避免无用的构造函数
    // good
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
        this.name = 'Rey';
      }
    }
    // bad
    class Jedi {
      constructor() {}
      getName() {
        return this.name;
      }
    }
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    使用 super 访问父类成员,而非父类的 prototype,不允许在子类中通过 super 修改父类成员。
    // good
    class TextNode extends Node {
      constructor(value, engine) {
        super(value);
        this.engine = engine;
      }
      setNodeValue(value) {
        super.setNodeValue(value);
        this.textContent = value;
      }
    }
    
    // bad
    class TextNode extends Node {
      constructor(value, engine) {
        Node.apply(this, value);
        this.engine = engine;
      }
      setNodeValue(value) {
        Node.prototype.setNodeValue.call(this, value);
        this.textContent = value;
      }
    }
    class TextNode extends Node {
      constructor(value, engine) {
        super(value);
        super.engine = engine;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    ES Module

    优先使用 ES Module
    // good
    import util from './util';
    export default function () {};
    
    // bad
    const util = require('./util');
    module.exports = function () {};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    export 与内容定义放在一起
    // good
    export function foo() {
    }
    
    // bad
    function foo() {
    }
    export { foo };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    import 语句写在模块开始处,dynamic import 除外
    // good
    import { bar } from './bar';
    function foo() {
      import('./foo').then(foo => console.log(foo));
      bar.work();
    }
    
    // bad
    function foo() {
      bar.work();
    }
    import { bar } from './bar';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    每一个文件以 default export 的形式暴露一个组件
    // good
    export default ComponentA;
    
    // bad
    const ComponentA = /* ... */;
    const ComponentB = /* ... */;
    export default {
      ComponentA,
      ComponentB
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    优先使用 named export
    禁止同一个文件中同时使用 ES Module export 和 CommonJS export

    CommonJS Module

    对于服务端 Node.js 的项目,可以使用 CommonJS Module
    禁止对 exports 赋值
    // good
    exports.foo = function foo() {
    };
    // good
    module.exports = function foo() {
    };
    
    // bad
    exports = function foo() {
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    参考: https://styleguide.bytedance.net/#/zh-cn/js?id=_3131-%e5%bb%ba%e8%ae%ae-%e5%9b%9e%e8%b0%83%e5%87%bd%e6%95%b0%e7%9a%84%e5%b5%8c%e5%a5%97%e4%b8%8d%e5%be%97%e8%b6%85%e8%bf%87-3-%e5%b1%82

  • 相关阅读:
    机器学习(八):决策树
    计算机三级 - 数据库技术 - 第十四章 数据仓库与数据挖掘 笔记
    Nginx快速入门&&部署前端项目
    申报设立2022年湖北省博士后创新实践基地条件、时间、流程
    Java练习题-获取数组元素最大值
    如何避免小程序被封
    STM32 CAN快速配置(HAL库版本)
    C++关键和宏
    泡椒凤爪制作教程
    浅谈ArrayList和LinkedList
  • 原文地址:https://blog.csdn.net/AnitaSun/article/details/126779977