Airbnb JavaScript 風(fēng)格指南

規(guī)范原則: 不可變原則 統(tǒng)一化原則 易讀易維護(hù)

類型


  • 1.1 基礎(chǔ)類型: 你可以直接獲取到基礎(chǔ)類型的值
    • string
    • number
    • boolean
    • null
    • undefined
    • symbol
      symbol 是es6新定義的類型失晴。不能被正確的polyfill顷蟀。所以不能在原生支持symbol類型的環(huán)境中使用
  • 1.2 復(fù)雜類型: 引用類型 給一個復(fù)雜類型賦值隅要。相當(dāng)于給他傳引用
    • object
    • array
    • function
const foo = [1, 2];
const bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9

賦值


  • 對于所有賦值使用const 不要使用var 這樣避免你重復(fù)賦值
  • 如果要修改賦值的話蘸秘。使用let來代替var 因?yàn)樗菈K級作用域
  • letconst都是塊級作用域 var是函數(shù)級作用域
{
  let a = 1;
  const b = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError

對象


  • 3.1 使用字面量復(fù)制來創(chuàng)建對象
// bad
var item = new Object();

// good
var item = {};
  • 3.2 使用計算后的屬性名來創(chuàng)建動態(tài)屬性名 這樣就可以放在一起了
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 atom = {
  value: 1,

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

// good
const atom = {
  value: 1,

  // 對象的方法
  addValue(value) {
    return atom.value + value;
  },
};
  • 3.4 用屬性值縮寫 更易讀和簡潔
const lukeSkywalker = 'Luke Skywalker';

// bad
const obj = {
  lukeSkywalker: lukeSkywalker,
};

// good
const obj = {
  lukeSkywalker,
};
  • 3.5 將簡寫的屬性值放在對性定義的開始
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';

// bad
const obj = {
  episodeOne: 1,
  twoJediWalkIntoACantina: 2,
  lukeSkywalker,
  episodeThree: 3,
  mayTheFourth: 4,
  anakinSkywalker,
};

// good
const obj = {
  lukeSkywalker,
  anakinSkywalker,
  episodeOne: 1,
  twoJediWalkIntoACantina: 2,
  episodeThree: 3,
  mayTheFourth: 4,
};
  • 3.6 對那些無效的表示使用引號'' 這樣優(yōu)化代碼高亮和易于壓縮
// bad
const bad = {
  'foo': 3,
  'bar': 4,
  'data-blah': 5,
};

// good
const good = {
  foo: 3,
  bar: 4,
  'data-blah': 5,
};
  • 3.7 不要直接調(diào)用Object.prototype方法 比如hasOwnProperty, isPrototypeOf. 因?yàn)槿绻@個對象是null 或者{hasOwnProperty: false}的話 會被屏蔽
// bad
console.log(object.hasOwnProperty(key));

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

// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
// ...
console.log(has.call(object, key));
  • 3.8 使用擴(kuò)展符號...來淺拷貝或者解構(gòu)一個對象 比Object.assign要好很多 清晰明了 不會修改之前對象
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // this mutates `original` ?_?
delete copy.a; // so does this

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

數(shù)組


// bad
var items = new Array();

// good
var items = [];
  • 4.2 使用 Array#push代替直接向數(shù)組中添加一個值
const someStack = [];

// bad
someStack[someStack.length] = 'abracadabra';

// good
someStack.push('abracadabra');
  • 4.3 使用擴(kuò)展運(yùn)算符...來復(fù)制數(shù)組
// bad
const len = items.length;
const itemsCopy = [];
let i;

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

// good
const itemsCopy = [...items];
  • 4.4 使用擴(kuò)展運(yùn)算符...而不是Array.from來將一個可迭代的對象轉(zhuǎn)換成數(shù)組廓奕。
const foo = document.querySelectorAll('.foo');

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

// best
const nodes = [...foo];
  • 4.5 使用Array.from來將一個類數(shù)組對象轉(zhuǎn)換為一個數(shù)組
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };

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

// good
const arr = Array.from(arrLike);
  • 4.6 使用Array.from代替擴(kuò)展運(yùn)算符...來做map遍歷 因?yàn)檫@樣可以避免生成一個臨時數(shù)組
// bad
const baz = [...foo].map(bar);
// good
const baz = Array.from(foo, baz);
  • 4.7 在數(shù)組方法的回調(diào)函數(shù)中使用 return 語句伟叛。 如果函數(shù)體由一條返回一個表達(dá)式的語句組成沽讹, 并且這個表達(dá)式?jīng)]有副作用晨川, 這個時候可以忽略return,詳見 8.2. eslint: array-callback-return
// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

// good 函數(shù)只有一個語句
[1, 2, 3].map(x => x + 1);

// bad - 沒有返回值彭谁, 因?yàn)樵诘谝淮蔚骯cc 就變成undefined了
[[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
  const flatten = acc.concat(item);
  acc[index] = flatten;
});

// good
[[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
  const flatten = acc.concat(item);
  acc[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;
});
  • 4.8 如果一個數(shù)組有很多行吸奴,在數(shù)組[后和]前斷行。
// 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,
];

解構(gòu)

  • 5.1 使用對象解構(gòu)來訪問對象某個或多個屬性值 因?yàn)榻鈽?gòu)保存了這些屬性的臨時值/引用
// 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}`;
}
const arr = [1, 2, 3, 4];

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

// good
const [first, second] = arr;
  • 5.3 對于返回多值的使用對象解構(gòu),而不是數(shù)組解構(gòu)则奥。這樣你可以后期添加新屬性或改變順序而不會打破原有的調(diào)用
// bad
function processInput(input) {
  // then a miracle occurs
  return [left, right, top, bottom];
}

// the caller needs to think about the order of return data
const [left, __, top] = processInput(input);

// good
function processInput(input) {
  // then a miracle occurs
  return { left, right, top, bottom };
}

// the caller selects only the data they need
const { left, top } = processInput(input);

字符串


  • 6.1 字符串使用單引號''
// bad
const name = "Capt. Janeway";

// bad - template literals should contain interpolation or newlines
const name = `Capt. Janeway`;

// good
const name = 'Capt. Janeway';
  • 6.2 超過100個字符不要使用字符串連接考润。因?yàn)樽址畵Q行難以閱讀和不便搜索
// 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.';
  • 6.3 使用模板字符串而不是字符串連接來組織編程字符串。 因?yàn)槟0遄址鬃x读处、語法簡潔糊治、字符串插入?yún)?shù)
// 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}?`;
}
  • 6.4 永遠(yuǎn)不要對于字符串使用eval(),可能會造成很多問題
  • 6.5 不要在字符串中引入非必要的轉(zhuǎn)義字符罚舱, 因?yàn)檗D(zhuǎn)義符會破壞字符串閱讀
// bad
const foo = '\'this\' \i\s \"quoted\"';

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

函數(shù)


  • 7.1 使用命名函數(shù)表達(dá)式來代替函數(shù)聲明

函數(shù)表達(dá)式: const func = function () {}
函數(shù)聲明: function func() {}
函數(shù)申明作用域被提前井辜,而且很容易在其定義之前被引用。這樣會破壞代碼可讀性和維護(hù)性

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

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

// good
// lexical name distinguished from the variable-referenced invocation(s)
const short = function longUniqueMoreDescriptiveLexicalFoo() {
  // ...
};
  • 7.2 使用圓括號來包裹立即執(zhí)行函數(shù), 但是在模塊化編程中基本很好用到IIFE
// immediately-invoked function expression (IIFE)
(function () {
  console.log('Welcome to the Internet. Please follow me.');
}());
  • 7.3 不要在if while等非函數(shù)塊聲明一個函數(shù)管闷≈嘟牛可以使用聲明一個函數(shù)變量代替。
  • 7.4 在ECMA-262中對于塊的定義是一系列的語句包个,而函數(shù)定義不是一個語句刷允。
// bad
if (currentUser) {
  function test() {
    console.log('Nope.');
  }
}

// good
let test;
if (currentUser) {
  test = () => {
    console.log('Yup.');
  };
}
  • 7.5 永遠(yuǎn)不要將一個參數(shù)命名成arguments 。這會導(dǎo)致arguments優(yōu)先執(zhí)行碧囊,會導(dǎo)致函數(shù)參數(shù)被覆蓋树灶。
// bad
function foo(name, options, arguments) {
  // ...
}

// good
function foo(name, options, args) {
  // ...
}
  • 7.6 用換不要使用arguments,可以使用擴(kuò)展符號...來代替
// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args.join('');
}

// good
function concatenateAll(...args) {
  return args.join('');
}
  • 7.7 使用函數(shù)默認(rèn)值糯而,而不是在函數(shù)中重新賦值
// really bad
function handleThings(opts) {
  // 不天通, 我們不該改arguments
  // 第二: 如果 opts 的值為 false, 它會被賦值為 {}
  // 雖然你想這么寫, 但是這個會帶來一些細(xì)微的bug
  opts = opts || {};
  // ...
}

// still bad
function handleThings(opts) {
  if (opts === void 0) {
    opts = {};
  }
  // ...
}

// good
function handleThings(opts = {}) {
  // ...
}
  • 7.8 默認(rèn)參數(shù)請避免副作用
var b = 1;
// bad
function count(a = b++) {
  console.log(a);
}
count();  // 1
count();  // 2
count(3); // 3
count();  // 3
// 所以 a到底是什么
  • 7.9 將默認(rèn)賦值熄驼,放在參數(shù)列表后面
// bad
function handleThings(opts = {}, name) {
  // ...
}

// good
function handleThings(name, opts = {}) {
  // ...
}
  • 7.10 永遠(yuǎn)不要使用Function來構(gòu)造一個新函數(shù) <=> 同理 string中使用eval()
// bad
var add = new Function('a', 'b', 'return a + b');

// still bad
var subtract = Function('a', 'b', 'return a - b');
  • 7.11 在函數(shù)前面前空格
// bad
const f = function(){};
const g = function (){};
const h = function() {};

// good
const x = function () {};
const y = function a() {};
  • 7.12 永遠(yuǎn)不要修改函數(shù)參數(shù) 這樣可能會導(dǎo)致不可預(yù)想的副作用(引用類型)
// bad
function f1(obj) {
  obj.key = 1;
}

// good
function f2(obj) {
  const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
}
  • 7.13 永遠(yuǎn)不要對函數(shù)參數(shù)重復(fù)賦值
// bad
function f1(a) {
  a = 1;
  // ...
}

function f2(a) {
  if (!a) { a = 1; }
  // ...
}

// good
function f3(a) {
  const b = a || 1;
  // ...
}

function f4(a = 1) {
  // ...
}
  • 7.14 使用擴(kuò)展運(yùn)算符...來調(diào)用多變函數(shù)像寒,更清晰,不必提供上下文
// 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]);
  • 7.15 函數(shù)包含多行參數(shù)的話谜洽,參考上方一個一行萝映。
// bad
function foo(bar,
             baz,
             quux) {
  // ...
}

// good
function foo(
  bar,
  baz,
  quux,
) {
  // ...
}

// bad
console.log(foo,
  bar,
  baz);

// good
console.log(
  foo,
  bar,
  baz,
);

箭頭函數(shù)


  • 8.1 當(dāng)你必須使用一個匿名函數(shù)的時候,使用箭頭函數(shù)阐虚。

Why? 他創(chuàng)建了一個this的當(dāng)前執(zhí)行上下文的函數(shù)的版本序臂,這通常就是你想要的积担;而且箭頭函數(shù)是更簡潔的語法
Why? 什么時候不用箭頭函數(shù): 如果你有一個相當(dāng)復(fù)雜的函數(shù)讲弄,你可能會把這個邏輯移出到他自己的函數(shù)聲明里棺克。

// bad
[1, 2, 3].map(function (x) {
  const y = x + 1;
  return x * y;
});

// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});
  • 8.2 如果 函數(shù)只是一條return 語句希停,忽略括號和return。
// bad
[1, 2, 3].map(number => {
  const nextNumber = number + 1;
  `A string containing the ${nextNumber}.`;
});

// good
[1, 2, 3].map(number => `A string containing the ${number}.`);

// good
[1, 2, 3].map((number) => {
  const nextNumber = number + 1;
  return `A string containing the ${nextNumber}.`;
});

// good
[1, 2, 3].map((number, index) => ({
  [index]: number
}));

// 表達(dá)式有副作用就不要用隱式return
function foo(callback) {
  const val = callback();
  if (val === true) {
    // Do something if callback returns true
  }
}

let bool = false;

// bad
// 這種情況會return bool = true, 不好
foo(() => bool = true);

// good
foo(() => {
  bool = true;
});
  • 8.3 萬一表達(dá)式涉及多行郑趁,把他包裹在圓括號里更可讀丛塌。 這樣清晰明了
// bad
['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call(
    httpMagicObjectWithAVeryLongName,
    httpMethod
  )
);

// good
['get', 'post', 'put'].map(httpMethod => (
  Object.prototype.hasOwnProperty.call(
    httpMagicObjectWithAVeryLongName,
    httpMethod
  )
));
  • 8.4 盡量簡化箭頭函數(shù)喧笔,減少視覺上干擾
// bad
[1, 2, 3].map((x) => x * x);

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

// good
[1, 2, 3].map(number => (
  `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
));

// bad
[1, 2, 3].map(x => {
  const y = x + 1;
  return x * y;
});

// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});
  • 8.5 避免箭頭函數(shù)(=>)和比較操作符(<=, >=)
// bad
const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;

// bad
const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;

// good
const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize);

// good
const itemHeight = (item) => {
  const { height, largeSize, smallSize } = item;
  return height > 256 ? largeSize : smallSize;
};
  • 8.6 在隱式return中強(qiáng)制約束函數(shù)體的位置避矢, 就寫在箭頭后面
// bad
foo =>
  bar;

foo =>
  (bar);

// good
foo => bar;
foo => (bar);
foo => (
   bar
)

類名和構(gòu)造函數(shù)


  • 9.1 使用類悼瘾,而不是直接操作屬性囊榜, 因?yàn)轭惛庇^、清晰
// bad
function Queue(contents = []) {
  this.queue = [...contents];
}
Queue.prototype.pop = function () {
  const value = this.queue[0];
  this.queue.splice(0, 1);
  return value;
};

// good
class Queue {
  constructor(contents = []) {
    this.queue = [...contents];
  }
  pop() {
    const value = this.queue[0];
    this.queue.splice(0, 1);
    return value;
  }
}
  • 9.2 使用extends來繼承亥宿。 內(nèi)置的方法來繼承原型而不打破instaceof
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
  Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function () {
  return this._queue[0];
}

// good
class PeekableQueue extends Queue {
  peek() {
    return this._queue[0];
  }
}
  • 9.3 方法可以返回this來實(shí)現(xiàn)方法鏈
// bad
Jedi.prototype.jump = function () {
  this.jumping = true;
  return true;
};

Jedi.prototype.setHeight = function (height) {
  this.height = height;
};

const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined

// good
class Jedi {
  jump() {
    this.jumping = true;
    return this;
  }

  setHeight(height) {
    this.height = height;
    return this;
  }
}

const luke = new Jedi();

luke.jump()
  .setHeight(20);
  • 9.4 可以在類里面自定義toString()方法卸勺,當(dāng)然請保證能夠正常工作和沒有副作用
  • 9.5 類如果沒有指定構(gòu)造方法的話,默認(rèn)包含一個構(gòu)造方法烫扼。沒有必要指定一個空的或者繼承父類的構(gòu)造方法曙求。
// bad
class Jedi {
  constructor() {}

  getName() {
    return this.name;
  }
}

// bad
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
  }
}

// good
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
    this.name = 'Rey';
  }
}
  • 9.6 避免重復(fù)類成員 相同的默認(rèn)會執(zhí)行最后一個。
// bad
class Foo {
  bar() { return 1; }
  bar() { return 2; }
}

// good
class Foo {
  bar() { return 1; }
}

// good
class Foo {
  bar() { return 2; }
}

模塊


  • 10.1 模塊化是未來映企,使用(import/export)而不是沒有標(biāo)準(zhǔn)的模塊化系統(tǒng)
// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;

// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;

// best
import { es6 } from './AirbnbStyleGuide';
export default es6;
  • 10.2 不要使用通配符(*)導(dǎo)入悟狱,這樣保證你有單個默認(rèn)的導(dǎo)出
// bad
import * as AirbnbStyleGuide from './AirbnbStyleGuide';

// good
import AirbnbStyleGuide from './AirbnbStyleGuide';
  • 10.3 不要直接導(dǎo)出在導(dǎo)入的時候。清晰分開導(dǎo)入和導(dǎo)出
// bad
// filename es6.js
export { es6 as default } from './AirbnbStyleGuide';

// good
// filename es6.js
import { es6 } from './AirbnbStyleGuide';
export default es6;
  • 10.4 在一個地方一次導(dǎo)入堰氓。這樣易于維護(hù)
// bad
import foo from 'foo';
// … some other imports … //
import { named1, named2 } from 'foo';

// good
import foo, { named1, named2 } from 'foo';

// good
import foo, {
  named1,
  named2,
} from 'foo';
  • 10.5 不要導(dǎo)出可變的東西挤渐。導(dǎo)出的東西應(yīng)該是常量
// bad
let foo = 3;
export { foo }

// good
const foo = 3;
export { foo }
  • 10.6 模塊化中,只有一個單獨(dú)的導(dǎo)出豆赏。最好使用default export挣菲。 這樣做的目的是鼓勵使用更多文件富稻,每個文件制作一件事情并導(dǎo)出掷邦,這樣可讀性和和維護(hù)性更好。
// bad
export function foo() {}

// good
export default function foo() {}
  • 10.7 import 放在其他所有語句之前 防止意外行為椭赋。
// bad
import foo from 'foo';
foo.init();

import bar from 'bar';

// good
import foo from 'foo';
import bar from 'bar';

foo.init();
  • 10.8 多行import應(yīng)該縮進(jìn)抚岗,就像多行數(shù)組和字面量
    // bad
    import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';

// good
import {
longNameA,
longNameB,
longNameC,
longNameD,
longNameE,
} from 'path';

  • 10.9 在import語句里不允許Webpack loader語法
// bad
import fooSass from 'css!sass!foo.scss';
import barCss from 'style!css!bar.css';

// good
import fooSass from 'foo.scss';
import barCss from 'bar.css';

迭代器和生成器


  • 11.1 不要使用迭代器。使用Js高級函數(shù)代替for-in哪怔、for-of

用數(shù)組的這些迭代方法: map() / every() / filter() / find() / findIndex() / reduce() / some() / ... , 用對象的這些方法 Object.keys() / Object.values() / Object.entries() 去產(chǎn)生一個數(shù)組宣蔚, 這樣你就能去遍歷對象了。

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 (use the functional force)
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;

// 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 (keeping it functional)
const increasedByOne = numbers.map(num => num + 1);

  • 11.2 現(xiàn)在不要用生成器认境。 因?yàn)樵趀s5上支持不好
  • 11.3 如果要使用生成器 請按照下面方式定義
// good
function* foo() {
  // ...
}

// good
const foo = function* () {
  // ...
};

屬性


  • 12.1 使用點(diǎn)符號來訪問屬性
const luke = {
  jedi: true,
  age: 28,
};

// bad
const isJedi = luke['jedi'];

// good
const isJedi = luke.jedi;
  • 12.2 如果屬性是變量的話胚委。使用方括號[]來訪問屬性
const luke = {
  jedi: true,
  age: 28,
};

function getProp(prop) {
  return luke[prop];
}

const isJedi = getProp('jedi');
  • 12.3 使用** 來計算乘方
// bad
const binary = Math.pow(2, 10);

// good
const binary = 2 ** 10;

變量

  • 13.1 使用constlet來定義變量,不然的話會污染全局變量
// bad
superPower = new SuperPower();

// good
const superPower = new SuperPower();
  • 13.2 定義變量一次一個 一個一行叉信。
// bad
const items = getItems(),
    goSportsTeam = true,
    dragonball = 'z';

// bad
// (compare to above, and try to spot the mistake)
const items = getItems(),
    goSportsTeam = true;
    dragonball = 'z';

// good
const items = getItems();
const goSportsTeam = true;
const dragonball = 'z';
  • 13.3 將const let分組
// bad
let i, len, dragonball,
    items = getItems(),
    goSportsTeam = true;

// bad
let i;
const items = getItems();
let dragonball;
const goSportsTeam = true;
let len;

// good
const goSportsTeam = true;
const items = getItems();
let dragonball;
let i;
let length;
  • 13.4 當(dāng)需要變量的時候申明亩冬,注意放在合適的位置
// bad - unnecessary function call
function checkName(hasName) {
  const name = getName();

  if (hasName === 'test') {
    return false;
  }

  if (name === 'test') {
    this.setName('');
    return false;
  }
  return name;
}

// good
function checkName(hasName) {
  if (hasName === 'test') {
    return false;
  }

  const name = getName();

  if (name === 'test') {
    this.setName('');
    return false;
  }

  return name;
}

  • 13.5 不要鏈接定義變量, 不好讀硼身,不好理解硅急。
// bad
(function example() {
  // JavaScript interprets this as
  // let a = ( b = ( c = 1 ) );
  // The let keyword only applies to variable a; variables b and c become
  // global variables.
  let a = b = c = 1;
}());

console.log(a); // throws ReferenceError
console.log(b); // 1
console.log(c); // 1

// good
(function example() {
  let a = 1;
  let b = a;
  let c = a;
}());

console.log(a); // throws ReferenceError
console.log(b); // throws ReferenceError
console.log(c); // throws ReferenceError

// the same applies for `const`
  • 13.6 不要使用一元自增 自減,自動分號插入解析問題
// bad

const array = [1, 2, 3];
let num = 1;
num++;
--num;

let sum = 0;
let truthyCount = 0;
for (let i = 0; i < array.length; i++) {
  let value = array[i];
  sum += value;
  if (value) {
    truthyCount++;
  }
}

// good

const array = [1, 2, 3];
let num = 1;
num += 1;
num -= 1;

const sum = array.reduce((a, b) => a + b, 0);
const truthyCount = array.filter(Boolean).length;
  • 13.7 在賦值的時候避免在=前后換行佳遂, 如果超出最長营袜,請使用小括號包裹再換行。
// bad
const foo =
  superLongLongLongLongLongLongLongLongFunctionName();

// bad
const foo
  = 'superLongLongLongLongLongLongLongLongString';

// good
const foo = (
  superLongLongLongLongLongLongLongLongFunctionName()
);

// good
const foo = 'superLongLongLongLongLongLongLongLongString';
  • 13.8 不允許有沒有使用的變量丑罪。在模塊化中一個變量沒有使用一個是困惑荚板。再者是一個不可預(yù)期的錯誤凤壁。
// bad

var some_unused_var = 42;

// Write-only variables are not considered as used.
var y = 10;
y = 5;

// A read for a modification of itself is not considered as used.
var z = 0;
z = z + 1;

// Unused function arguments.
function getX(x, y) {
    return x;
}

// good

function getXPlusY(x, y) {
  return x + y;
}

var x = 1;
var y = a + 2;

alert(getXPlusY(x, y));

// 'type' is ignored even if unused because it has a rest property sibling.
// This is a form of extracting an object that omits the specified keys.
var { type, ...coords } = data;
// 'coords' is now the 'data' object without its 'type' property.

提升作用域


  • 14.1 使用var定義
  • 14.2 匿名函數(shù)表達(dá)式和 var 情況相同
function example() {
  console.log(anonymous); // => undefined

  anonymous(); // => TypeError anonymous is not a function

  var anonymous = function () {
    console.log('anonymous function expression');
  };
}
  • 14.3 已命名函數(shù)表達(dá)式提升他的變量名,不是函數(shù)名或函數(shù)體
  • 14.4 函數(shù)聲明則提升了函數(shù)名和函數(shù)體

比較運(yùn)算符


  • 15.1 使用===!== 而不是== !=
  • 15.2 比較的時候跪另,類型參考以下轉(zhuǎn)換
    • Object 計算成 true
    • undefined 計算成 false
    • NUll 計算成false
    • Numbers [+0客扎、-0、NaN] 計算成false 其他true
    • String [''] 計算成false 其他true
if ([0] && []) {
  // true
  // 數(shù)組(即使是空數(shù)組)是對象罚斗,對象會計算成true
}
  • 15.3 booleans判斷使用簡寫徙鱼,但是對于字符串和數(shù)字要明確
// bad
if (isValid === true) {
  // ...
}

// good
if (isValid) {
  // ...
}

// bad
if (name) {
  // ...
}

// good
if (name !== '') {
  // ...
}

// bad
if (collection.length) {
  // ...
}

// good
if (collection.length > 0) {
  // ...
}
  • 15.4 For more information see Truth Equality and JavaScript by Angus Croll.
  • 15.5 使用花括號在case default創(chuàng)造塊作用域 主要是應(yīng)對case分句定義同一個事情出問題
// bad
switch (foo) {
  case 1:
    let x = 1;
    break;
  case 2:
    const y = 2;
    break;
  case 3:
    function f() {
      // ...
    }
    break;
  default:
    class C {}
}

// good
switch (foo) {
  case 1: {
    let x = 1;
    break;
  }
  case 2: {
    const y = 2;
    break;
  }
  case 3: {
    function f() {
      // ...
    }
    break;
  }
  case 4:
    bar();
    break;
  default: {
    class C {}
  }
}
  • 15.6 三元表達(dá)式不應(yīng)該嵌套,通常是單行表達(dá)式针姿。
// bad
const foo = maybe1 > maybe2
  ? "bar"
  : value1 > value2 ? "baz" : null;

// better
const maybeNull = value1 > value2 ? 'baz' : null;

const foo = maybe1 > maybe2
  ? 'bar'
  : maybeNull;

// best
const maybeNull = value1 > value2 ? 'baz' : null;

const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
  • 15.7 避免不需要的三元表達(dá)式
// bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;

// good
const foo = a || b;
const bar = !!c;
const baz = !c;
  • 15.8 用圓括號來做語意隔絕袱吆,這樣優(yōu)先級一目了然和可讀性也更好
// bad
const foo = a && b < 0 || c > 0 || d + 1 === 0;

// bad
const bar = a ** b - 5 % d;

// bad
// 別人會陷入(a || b) && c 的迷惑中
if (a || b && c) {
  return d;
}

// good
const foo = (a && b < 0) || c > 0 || (d + 1 === 0);

// good
const bar = (a ** b) - (5 % d);

// good
if (a || (b && c)) {
  return d;
}

// good
const bar = a + b / c * d;


  • 16.1 用大括號包裹多行代碼塊
// bad
if (test)
  return false;

// good
if (test) return false;

// good
if (test) {
  return false;
}

// bad
function foo() { return false; }

// good
function bar() {
  return false;
}
  • 16.2 如果要使用if elseelse放在if關(guān)閉括號同一行
// bad
if (test) {
  thing1();
  thing2();
}
else {
  thing3();
}

// good
if (test) {
  thing1();
  thing2();
} else {
  thing3();
}
  • 16.3 如果if語句 有return 語句, 后續(xù)語句else return就不是必須
// bad
function foo() {
  if (x) {
    return x;
  } else {
    return y;
  }
}

// bad
function cats() {
  if (x) {
    return x;
  } else if (y) {
    return y;
  }
}

// bad
function dogs() {
  if (x) {
    return x;
  } else {
    if (y) {
      return y;
    }
  }
}

// good
function foo() {
  if (x) {
    return x;
  }

  return y;
}

// good
function cats() {
  if (x) {
    return x;
  }

  if (y) {
    return y;
  }
}

// good
function dogs(x) {
  if (x) {
    if (z) {
      return y;
    }
  } else {
    return z;
  }
}
  • 17.1 如果控制語句(if, while 等)太長或者超過最大長度限制的時候距淫,把每一個判斷條件單獨(dú)放在一行里面绞绒,邏輯操作放在行首。提高可讀性
// bad
if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
  thing1();
}

// bad
if (foo === 123 &&
  bar === 'abc') {
  thing1();
}

// bad
if (foo === 123
  && bar === 'abc') {
  thing1();
}

// bad
if (
  foo === 123 &&
  bar === 'abc'
) {
  thing1();
}

// good
if (
  foo === 123
  && bar === 'abc'
) {
  thing1();
}

// good
if (
  (foo === 123 || bar === 'abc')
  && doesItLookGoodWhenItBecomesThatLong()
  && isThisReallyHappening()
) {
  thing1();
}

// good
if (foo === 123 && bar === 'abc') {
  thing1();
}
  • 17.2 不要用選擇控制符代替控制語句
// bad
!isRunning && startRunning();

// good
if (!isRunning) {
  startRunning();
}

注釋


  • 18.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;
}
  • 18.2 單行注釋用//榕暇,將單行注釋放在被注釋區(qū)域上面蓬衡。如果注釋不是在第一行,那么注釋前面就空一行
// 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;
}
  • 18.3 所有注釋開頭空一格
// 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;
}
  • 18.4 使用FIXME 或者TODO
  • 18.5 使用FIXME
class Calculator extends Abacus {
  constructor() {
    super();

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

    // TODO: total should be configurable by an options param
    this.total = 0;
  }
}

空格


  • 19.1 tab 使用兩個空格
function foo() {
????const name;
}

// bad
function bar() {
?const name;
}

// good
function baz() {
??const name;
}
  • 19.2 在大括號前空一格
// bad
function test(){
  console.log('test');
}

// good
function test() {
  console.log('test');
}

// bad
dog.set('attr',{
  age: '1 year',
  breed: 'Bernese Mountain Dog',
});

// good
dog.set('attr', {
  age: '1 year',
  breed: 'Bernese Mountain Dog',
});
  • 19.3 在控制語句(if, while 等)的圓括號前空一格彤枢。在函數(shù)調(diào)用和定義時狰晚,參數(shù)列表和函數(shù)名之間不空格
// bad
if(isJedi) {
  fight ();
}

// good
if (isJedi) {
  fight();
}

// bad
function fight () {
  console.log ('Swooosh!');
}

// good
function fight() {
  console.log('Swooosh!');
}
  • 19.4 用空格來隔開運(yùn)算符
// bad
const x=y+5;

// good
const x = y + 5;
  • 19.5 文件結(jié)尾空格
// good
import { es6 } from './AirbnbStyleGuide';
  // ...
export default es6;?
  • 19.5 出現(xiàn)長的方法鏈(>2個)時 用縮進(jìn) 用電開頭強(qiáng)調(diào)該行是一個方法調(diào)用,而不是一個新的語句
// bad
$('#items').find('.selected').highlight().end().find('.open').updateCount();

// bad
$('#items').
  find('.selected').
    highlight().
    end().
  find('.open').
    updateCount();

// good
$('#items')
  .find('.selected')
    .highlight()
    .end()
  .find('.open')
    .updateCount();

// bad
const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
    .attr('width', (radius + margin) * 2).append('svg:g')
    .attr('transform', `translate(${radius + margin},${radius + margin})`)
    .call(tron.led);

// good
const leds = stage.selectAll('.led')
    .data(data)
  .enter().append('svg:svg')
    .classed('led', true)
    .attr('width', (radius + margin) * 2)
  .append('svg:g')
    .attr('transform', `translate(${radius + margin},${radius + margin})`)
    .call(tron.led);

// good
const leds = stage.selectAll('.led').data(data);
  • 19.7 在一個代碼塊后一條語句前空一行
// bad
if (foo) {
  return bar;
}
return baz;

// good
if (foo) {
  return bar;
}

return baz;

// bad
const obj = {
  foo() {
  },
  bar() {
  },
};
return obj;

// good
const obj = {
  foo() {
  },

  bar() {
  },
};

return obj;

// bad
const arr = [
  function foo() {
  },
  function bar() {
  },
];
return arr;

// good
const arr = [
  function foo() {
  },

  function bar() {
  },
];

return arr;
  • 19.8 不要用空行填充塊
// bad
function bar() {

  console.log(foo);

}

// bad
if (baz) {

  console.log(qux);
} else {
  console.log(foo);

}

// bad
class Foo {

  constructor(bar) {
    this.bar = bar;
  }
}

// good
function bar() {
  console.log(foo);
}

// good
if (baz) {
  console.log(qux);
} else {
  console.log(foo);
}
  • 19.9 圓括號不好加空格
// bad
function bar( foo ) {
  return foo;
}

// good
function bar(foo) {
  return foo;
}

// bad
if ( foo ) {
  console.log(foo);
}

// good
if (foo) {
  console.log(foo);
}
  • 19.11 方括號不要加空格
// bad
const foo = [ 1, 2, 3 ];
console.log(foo[ 0 ]);

// good缴啡, 逗號分隔符還是要空格的
const foo = [1, 2, 3];
console.log(foo[0]);
  • 19.12 花括號加空格
// bad
const foo = {clark: 'kent'};

// good
const foo = { clark: 'kent' };
  • 19.12 避免一行代碼超過100個字符(包括空格) 但是字符串表述的時候不受限制
  • 19.13 作為語句的花括號也要加空格
// bad
function foo() {return true;}
if (foo) { bar = 0;}

// good
function foo() { return true; }
if (foo) { bar = 0; }
  • 19.14 , 前不要加空格
// bad
var foo = 1,bar = 2;
var arr = [1 , 2];

// good
var foo = 1, bar = 2;
var arr = [1, 2];
  • 19.15 計算屬性內(nèi)要空格
// bad
obj[foo ]
obj[ 'foo']
var x = {[ b ]: a}
obj[foo[ bar ]]

// good
obj[foo]
obj['foo']
var x = { [b]: a }
obj[foo[bar]]
  • 19.16 調(diào)用函數(shù)時壁晒,函數(shù)名和小括號不要空格
// bad
func ();

func
();

// good
func();
  • 19.17 在對象的字面量屬性中, key value 之間要有空格
// bad
var obj = { "foo" : 42 };
var obj2 = { "foo":42 };

// good
var obj = { "foo": 42 }
  • 19.18 行末不要空格
  • 19.19 避免出現(xiàn)多個空行业栅。在文件末尾只允許空一行
// bad
var x = 1;



var y = 2;

// good
var x = 1;

var y = 2;

逗號


  • 20.1 不要前置逗號
    // bad
    const story = [
    once
    , upon
    , aTime
    ];

// good
const story = [
once,
upon,
aTime,
];

// bad
const hero = {
firstName: 'Ada'
, lastName: 'Lovelace'
, birthYear: 1815
, superPower: 'computers'
};

// good
const hero = {
firstName: 'Ada',
lastName: 'Lovelace',
birthYear: 1815,
superPower: 'computers',
};

  • 20.2 額外結(jié)尾逗號秒咐,主要是為了git diffs 更清潔
// bad - 沒有結(jié)尾逗號的 git diff
const hero = {
     firstName: 'Florence',
-    lastName: 'Nightingale'
+    lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing']
};

// good - 有結(jié)尾逗號的 git diff
const hero = {
     firstName: 'Florence',
     lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing'],
};

分號


  • 21.1

Why? 當(dāng) JavaScript 遇到?jīng)]有分號結(jié)尾的一行,它會執(zhí)行自動插入分號 Automatic Semicolon Insertion這一規(guī)則來決定行末是否加分號碘裕。如果JavaScript在你的斷行里錯誤的插入了分號携取,就會出現(xiàn)一些古怪的行為。當(dāng)新的功能加到JavaScript里后帮孔, 這些規(guī)則會變得更復(fù)雜難懂雷滋。顯示的結(jié)束語句,并通過配置代碼檢查去捕獲沒有帶分號的地方可以幫助你防止這種錯誤你弦。

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

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

// good, 行首加分號惊豺,避免文件被連接到一起時立即執(zhí)行函數(shù)被當(dāng)做變量來執(zhí)行。
;(() => {
  const name = 'Skywalker';
  return name;
}());

類型強(qiáng)制轉(zhuǎn)化

  • 22.1 在語句開始執(zhí)行強(qiáng)制類型轉(zhuǎn)換禽作。
  • 22.2 String
// bad
const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"

// bad
const totalScore = this.reviewScore + ''; // invokes this.reviewScore.valueOf()

// bad
const totalScore = this.reviewScore.toString(); // 不保證返回string

// good
const totalScore = String(this.reviewScore);
  • 22.3 Numbers: 用 Number 做類型轉(zhuǎn)換尸昧,parseInt轉(zhuǎn)換string常需要帶上基數(shù)。 eslint: radix
const inputValue = '4';

// bad
const val = new Number(inputValue);

// bad
const val = +inputValue;

// bad
const val = inputValue >> 0;

// bad
const val = parseInt(inputValue);

// good
const val = Number(inputValue);

// good
const val = parseInt(inputValue, 10);
  • 22.4 位運(yùn)算
  • 22.5
  • 22.6 布爾
const age = 0;

// bad
const hasAge = new Boolean(age);

// good
const hasAge = Boolean(age);

// best
const hasAge = !!age;

命名


  • 23.1 避免使用一個字母命名旷偿,應(yīng)該言有所指 eslint: id-length
function q() {
  // ...
}

// good
function query() {
  // ...
}
  • 23.2 用小駝峰式命名你的對象烹俗、函數(shù)爆侣、實(shí)例。 eslint: camelcase
// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}

// good
const thisIsMyObject = {};
function thisIsMyFunction() {}
  • 23.3 用大駝峰式命名類幢妄。 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',
});

Why? JavaScript 沒有私有屬性或私有方法的概念。盡管前置下劃線通常的概念上意味著“private”蕉鸳,事實(shí)上乎赴,這些屬性是完全公有的,因此這部分也是你的API的內(nèi)容潮尝。這一概念可能會導(dǎo)致開發(fā)者誤以為更改這個不會導(dǎo)致崩潰或者不需要測試榕吼。 如果你想要什么東西變成“private”,那就不要讓它在這里出現(xiàn)勉失。

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

// good
this.firstName = 'Panda';
// bad
function foo() {
  const self = this;
  return function () {
    console.log(self);
  };
}

// bad
function foo() {
  const that = this;
  return function () {
    console.log(that);
  };
}

// good
function foo() {
  return () => {
    console.log(this);
  };
}
  • 23.6 export default導(dǎo)出模塊A,則這個文件名也叫A.*乱凿, import 時候的參數(shù)也叫A顽素。 大小寫完全一致。
// file 1 contents
class CheckBox {
  // ...
}
export default CheckBox;

// file 2 contents
export default function fortyTwo() { return 42; }

// file 3 contents
export default function insideDirectory() {}

// in some other file
// bad
import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename
import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export
import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export

// bad
import CheckBox from './check_box'; // PascalCase import/export, snake_case filename
import forty_two from './forty_two'; // snake_case import/filename, camelCase export
import inside_directory from './inside_directory'; // snake_case import, camelCase export
import index from './inside_directory/index'; // requiring the index file explicitly
import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly

// good
import CheckBox from './CheckBox'; // PascalCase export/import/filename
import fortyTwo from './fortyTwo'; // camelCase export/import/filename
import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index"
// ^ supports both insideDirectory.js and insideDirectory/index.js
  • 23.7 當(dāng)你export-default一個函數(shù)時徒蟆,函數(shù)名用小駝峰胁出,文件名需要和函數(shù)名一致。
function makeStyleGuide() {
  // ...
}

export default makeStyleGuide;
  • 23.8 當(dāng)你export一個結(jié)構(gòu)體/類/單例/函數(shù)庫/對象 時用大駝峰后专。
const AirbnbStyleGuide = {
  es6: {
  }
};

export default AirbnbStyleGuide;
  • 23.9 簡稱和縮寫應(yīng)該全部大寫或全部小寫划鸽。
// bad
import SmsContainer from './containers/SmsContainer';

// bad
const HttpRequests = [
  // ...
];

// good
import SMSContainer from './containers/SMSContainer';

// good
const HTTPRequests = [
  // ...
];

// best
import TextMessageContainer from './containers/TextMessageContainer';

// best
const Requests = [
  // ...
];
  • 23.10
    你可以用全大寫字母設(shè)置靜態(tài)變量,他需要滿足三個條件戚哎。

導(dǎo)出變量
是 const 定義的, 保證不能被改變
這個變量是可信的嫂用,他的子屬性都是不能被改變的
Why? 這是一個附加工具型凳,幫助開發(fā)者去辨識一個變量是不是不可變的。

對于所有的 const 變量呢嘱函? —— 這個是不必要的甘畅。大寫變量不應(yīng)該在同一個文件里定義并使用, 它只能用來作為導(dǎo)出變量往弓。 贊同疏唾!
那導(dǎo)出的對象呢? —— 大寫變量處在export的最高級(e.g. EXPORTED_OBJECT.key) 并且他包含的所有子屬性都是不可變的函似。

// bad
const PRIVATE_VARIABLE = 'should not be unnecessarily uppercased within a file';

// bad
export const THING_TO_BE_CHANGED = 'should obviously not be uppercased';

// bad
export let REASSIGNABLE_VARIABLE = 'do not use let with uppercase variables';

// ---

// allowed but does not supply semantic value
export const apiKey = 'SOMEKEY';

// better in most cases
export const API_KEY = 'SOMEKEY';

// ---

// bad - unnecessarily uppercases key while adding no semantic value
export const MAPPING = {
  KEY: 'value'
};

// good
export const MAPPING = {
  key: 'value'
};

訪問器


  • 24.1 不需要使用屬性的訪問器函數(shù)槐脏。
  • 24.2 不要使用JavaScript的getters/setters,因?yàn)樗麄儠a(chǎn)生副作用撇寞,并且難以測試顿天、維護(hù)和理解堂氯。相反的,你可以用 getVal()和setVal('hello')去創(chuàng)造你自己的accessor函數(shù)
// bad
class Dragon {
  get age() {
    // ...
  }

  set age(value) {
    // ...
  }
}

// good
class Dragon {
  getAge() {
    // ...
  }

  setAge(value) {
    // ...
  }
}
  • 24.3 如果屬性/方法是boolean牌废, 用 isVal() 或 hasVal()
// bad
if (!dragon.age()) {
  return false;
}

// good
if (!dragon.hasAge()) {
  return false;
}
  • 24.4 用get()和set()函數(shù)是可以的咽白,但是要一起用
class Jedi {
  constructor(options = {}) {
    const lightsaber = options.lightsaber || 'blue';
    this.set('lightsaber', lightsaber);
  }

  set(key, val) {
    this[key] = val;
  }

  get(key) {
    return this[key];
  }
}

事件


jQuery


  • 26.1 jQuery對象用$變量表示
// bad
const sidebar = $('.sidebar');

// good
const $sidebar = $('.sidebar');

// good
const $sidebarBtn = $('.sidebar-btn');
  • 26.2 暫存jQuery查找
// bad
function setSidebar() {
  $('.sidebar').hide();

  // ...

  $('.sidebar').css({
    'background-color': 'pink'
  });
}

// good
function setSidebar() {
  const $sidebar = $('.sidebar');
  $sidebar.hide();

  // ...

  $sidebar.css({
    'background-color': 'pink'
  });
}
  • 26.3 DOM查找用層疊式$('.sidebar ul') 或 父節(jié)點(diǎn) > 子節(jié)點(diǎn) $('.sidebar > ul'). jsPerf
  • 26.4 用jQuery對象查詢作用域的find方法查詢
// bad
$('ul', '.sidebar').hide();

// bad
$('.sidebar').find('ul').hide();

// good
$('.sidebar ul').hide();

// good
$('.sidebar > ul').hide();

// good
$sidebar.find('ul').hide();

ES5 兼容性


ECMAScript 6+ (ES 2015+) Styles

  1. 箭頭函數(shù)——Arrow Functions
  2. 類——Classes
  3. 對象縮寫——Object Shorthand
  4. 對象簡寫——Object Concise
  5. 對象計算屬性——Object Computed Properties
  6. 模板字符串——Template Strings
  7. 解構(gòu)賦值——Destructuring
  8. 默認(rèn)參數(shù)——Default Parameters
  9. Rest
  10. Array Spreads
  11. Let and Const
  12. 冪操作符——Exponentiation Operator
  13. 迭代器和生成器——Iterators and Generators
  14. 模塊——Modules

標(biāo)準(zhǔn)庫

// bad
isNaN('1.2'); // false
isNaN('1.2.3'); // true

// good
Number.isNaN('1.2.3'); // false
Number.isNaN(Number('1.2.3')); // true
// bad
isFinite('2e3'); // true

// good
Number.isFinite('2e3'); // false
Number.isFinite(parseInt('2e3', 10)); // true
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鸟缕,隨后出現(xiàn)的幾起案子晶框,更是在濱河造成了極大的恐慌,老刑警劉巖懂从,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件三妈,死亡現(xiàn)場離奇詭異,居然都是意外死亡莫绣,警方通過查閱死者的電腦和手機(jī)畴蒲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來对室,“玉大人模燥,你說我怎么就攤上這事⊙谝耍” “怎么了蔫骂?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長牺汤。 經(jīng)常有香客問我辽旋,道長,這世上最難降的妖魔是什么檐迟? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任补胚,我火速辦了婚禮,結(jié)果婚禮上追迟,老公的妹妹穿的比我還像新娘溶其。我一直安慰自己,他們只是感情好敦间,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布瓶逃。 她就那樣靜靜地躺著,像睡著了一般廓块。 火紅的嫁衣襯著肌膚如雪厢绝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天带猴,我揣著相機(jī)與錄音昔汉,去河邊找鬼。 笑死浓利,一個胖子當(dāng)著我的面吹牛挤庇,可吹牛的內(nèi)容都是我干的钞速。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嫡秕,長吁一口氣:“原來是場噩夢啊……” “哼渴语!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起昆咽,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤驾凶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后掷酗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體调违,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年泻轰,在試婚紗的時候發(fā)現(xiàn)自己被綠了技肩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡浮声,死狀恐怖虚婿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情泳挥,我是刑警寧澤然痊,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站屉符,受9級特大地震影響剧浸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜矗钟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一唆香、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧真仲,春花似錦袋马、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碑宴。三九已至软啼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間延柠,已是汗流浹背祸挪。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贞间,地道東北人贿条。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓雹仿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親整以。 傳聞我的和親對象是個殘疾皇子胧辽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355