导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

算法

UI、组件库

Node

业务技能

针对性攻坚

AI

公共类


语言规范

JavaScript 是一种客户端脚本语言,这里列出了编写 JavaScript 时需要遵守的规则。

类型

引用

{
  let a = 1;
  const b = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError

原因:这样做可以确保你无法重新分配引用,以避免出现错误和难以理解的代码

// bad
var a = 1;
var b = 2;

// good
const a = 1;
const b = 2;

原因:let 是块级作用域的,而不像 var 属于函数级作用域

// bad
var count = 1;
if (count < 10) {
  count += 1;
}

// good
let count = 1;
if (count < 10) {
  count += 1;
}

对象

// bad
const a = new Object{};

// good
const a = {};
// bad
const a = {
  default: {},  // default 是保留字
  common: {}
};

// good
const a = {
  defaults: {},
  common: {}
};

原因:因为这样做就可以让你在一个地方定义所有的对象属性

function getKey(k) {
  return `a key named ${k}`;
}

// bad
const obj = {
  id: 5,
  name: 'San Francisco'
};
obj[getKey('enabled')] = true;

// good
const obj = {
  id: 5,
  name: 'San Francisco',
  [getKey('enabled')]: true
};
// bad
const item = {
  value: 1,

  addValue: function (val) {
    return item.value + val;
  }
};

// good
const item = {
  value: 1,

  addValue (val) {
    return item.value + val;
  }
};

原因:这样更简短且描述更清楚

const job = 'FrontEnd';

// bad
const item = {
  job: job
};

// good
const item = {
  job
};

原因:这样更容易区分哪些属性用了简写的方式

const job = 'FrontEnd';
const department = 'One';

// bad
const item = {
  sex: 'male',
  job,
  age: 25,
  department
};

// good
const item = {
  job,
  department,
  sex: 'male',
  age: 25
};

原因:因为通常来说我们认为这样主观上会更容易阅读,这样会带来代码高亮上的提升,同时也更容易被主流 JS 引擎优化

// bad
const bad = {
  'foo': 3,
  'bar': 4,
  'data-blah': 5
};

// good
const good = {
  foo: 3,
  bar: 4,
  'data-blah': 5
};

原因:这些方法可能会被对象自身的同名属性覆盖 - 比如 { hasOwnProperty: false } 或者对象可能是一个 null 对象(Object.create(null))

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

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

// best
const has = Object.prototype.hasOwnProperty; // 缓存一次查找,在模块作用域内
console.log(has.call(object, key));
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // 这会改变`original` ಠ_ಠ
delete copy.a; // original G 了

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

数组

// bad
const items = new Array();

// good
const items = [];
const items = [];

// bad
items[items.length] = 'test';

// good
items.push('test');
// bad
const items = [];
const itemsCopy = [];
const len = items.length;
let i;

// bad
for (i = 0; i < len; i++) {
  itemsCopy[i] = items[i];
}

// good
itemsCopy = [...items];
const foo = document.querySelectorAll('.foo');

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

// best
const nodes = [...foo];
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };

// bad
const arr = Array.prototype.slice.call(arrLike);

// good
const arr = Array.from(arrLike);
// bad
const baz = [...foo].map(bar);

// good
const baz = Array.from(foo, bar);
// good
[1, 2, 3].map(x => {
  const y = x + 1;
  return x * y;
})

// good
[1, 2, 3].map(x => x + 1);

// bad
const flat = {};
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
  const flatten = memo.concat(item);
  flat[index] = flatten;
})

// good
const flat = {};
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
  const flatten = memo.concat(item);
  flat[index] = flatten;
  return flatten;
})

// bad
inbox.filter((msg) => {
  const { subject, author } = msg;
  if (subject === 'Mockingbird') {
    return author === 'Harper Lee';
  } else {
    return false;
  }
})

// good
inbox.filter((msg) => {
  const { subject, author } = msg;
  if (subject === 'Mockingbird') {
    return author === 'Harper Lee';
  }

  return false;
})
// bad
const arr = [
  [0, 1], [2, 3], [4, 5]
];

const objectInArray = [{
  id: 1
}, {
  id: 2
}];

const numberInArray = [
  1, 2
];

// good
const arr = [[0, 1], [2, 3], [4, 5]];

const objectInArray = [
  {
    id: 1
  },
  {
    id: 2
  }
];

const numberInArray = [
  1,
  2
];

解构赋值

愿意:解构可以避免创建属性的临时引用

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

// better
function getFullName ({ firstName, lastName }) {
  return `${firstName} ${lastName}`;
}
const arr = [1, 2, 3, 4];

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

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

原因:可以非破坏性地随时增加或者改变属性顺序

// bad
function doSomething () {
  return [top, right, bottom, left];
}

// 如果是数组解构,那么在调用时就需要考虑数据的顺序
const [top, xx, xxx, left] = doSomething();

// good
function doSomething () {
  return { top, right, bottom, left };
}

// 此时不需要考虑数据的顺序
const { top, left } = doSomething();

字符串

// bad
const department = "One";

// good
const department = 'One';
const str = '前端开发规范 前端开发规范 前端开发规范' +
  '前端开发规范 前端开发规范' +
  '前端开发规范';
const test = 'test';

// bad
const str = ['a', 'b', test].join();

// bad
const str = 'a' + 'b' + test;

// good
const str = `ab${test}`;
// bad
const foo = '\\'this\\' \\i\\s \\"quoted\\"';

// good
const foo = '\\'this\\' is "quoted"';
const foo = `my name is '${name}'`;

函数