js风格指南

208 阅读20分钟

JavaScript风格指南

Types

1.1 访问原始类型时 , 直接处理其值

const foo = 1;
let bar = foo
bar = 9
console.log(foo,bar) // => 1 , 9

1.2 访问复杂类型时 , 处理对其值的引用

const foo = [1,2];
const bar = foo;
bar[0] = 9;
console.log(foo[0],bar[0]) // => 9 , 9

References

2.1 对所有引用使用const , 避免使用var

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

2.2 如果必须重新分配引用 , 请使用let而不是用var

//bad
var count = 1;
if (true) {
  const += 1
}
//good , use the let
let count = 1;
if (true) {
  count += 1;
}

2.3 let 和const 都是块范围 , var是函数范围

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

Objects

3.1 使用字面量创建对象

//bad
const item = new Object();
//good
const item = {};

3.2 创建具有动态属性名称的对象时,使用计算属性名称

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
}

3.3 使用对象方法简写

//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 = 'Luck 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 仅引用无效标识符的属性

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

3.7 不要直接调用 Object.prototype 方法 , 这些方法可能会被相关对象的属性所掩盖

//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))
/* or */
import has from 'has';
console.log(has(object,key))

3.8 优先使用对象扩展语法而不是Object.assign浅拷贝对象 ,使用对象休息运算符来获取省略某些属性的新对象

//very bad
const original = {a:1,b:2}
const copy = Object.assign(original,{c:3});  // 改变了原始值
delete copy.a
//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 } = {b:2 , c:3 }

Arrays

4.1 使用字面量创建数组

//bad
const items = new Array()
//good
const items = []

4.2 使用push而不是通过赋值来添加项

const someStack = [];
//bad
someSkack[someStack.length] = 'abracadabra';
//good
someStack.push('abracadabra')

4.3 使用扩展运算符复制数组

3//bad
const len = items.length
const itemCopy = [];
let i;
for (i = 0;i<len;i += 1){
  itemCopy[i] = items[i]
} 
//good
const itemCopy = [...items]

4.4 要将可迭代对象转换为数组 , 请使用扩展运算符而不是Array.from

const foo = document.querySelectorAll('.foo');
//good
const nodes = Array.from(foo);
//bast
const nodes = [...foo]

4.5 使用Array.from 将类数转换为数组

const results = {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 而不是 ... 来映射可迭代对象 , 避免创建中间数组

//bad
const baz = [...foo].map(bar); //创建了中间数组后再进行映射
//good
const arr = Array.from(foo,bar)

4.7 在数组方法回调中使用return语句 ,如果函数体由单个语句组成 , 返回一个没有副作用的表达式 , 可以省略return

//good
[1,2,3].map((x)=>{
  const y = x + 1;
  return x * y
})
//good
[1,2,3].map(x=>x+1);
//bad 没有返回值意味着 `acc` 在第一次迭代后变得未定义
[[0,1],[2,3],[4,5]].reduce((acc,item,index)=>{
  const flatten = acc.concat(item)
})
//good
[[0,1],[2,3],[4,5]].reduce((acc,item,index)=>{
  const flatten = acc.concat(item)
  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 如果数组有多行 , 则在打开数组括号之后和关闭数组括号之前使用换行符

//bad
const arr  = [
  [0,1],[2,3],[4,5]  
]
const objetInArray = [{
  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,
];

Destructuring (解构)

5.1 在访问和使用对象的多个属性时使用对象解构

//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}`
}
//bast
function getFullName({firstName,lastName}){
  return `${firstName} ${lastName}`
}

5.2 数组解构

const arr = [1,2,3,4];
//bad
const first = arr[0];
const second = arr[1];
//good
const [first,second] = arr

5.3 对多个返回值使用对象解构 , 而不是数组解构

//bad
function processInput (input) {
  return [left,right,top,bottom]
}
// 调用者需要考虑返回数据的顺序
const [left,__,top] = processInput(input)

//good
function processInput(input) {
  return {left,right,top,bottom}
}
//调用者只需要选择他们需要的数据
const {left,top}  = processInput(input)

Strings

6.1 使用单引号

//bad
const name = "Capt. Janeway"
// bad 模板文字应包含插值或换行符
const name = `Capt. Janeway`
//good
const name = 'Capt. Janeway'

6.2 不应使用字符串串联将导致该行超过100个字符的字符串写入多行

// 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 以编程方式构建字符串时 , 使用模板字符串而不是串联

//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 永远不要在字符串上使用 eval(),它会产生太多漏洞

6.5 不要对字符串中的字符进行不必要的转义。

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

Function

7.1 使用函数表达式而不是函数声明

原因 : 函数声明被提升 , 导致在函数定义之前引用函数很容易 , 将会损害可读性和可维护性 , 如果一个函数过于复杂 , 可以将其提取到自己的模块中 , 不要忘了显式命名表达式 , 无论名称是否从包含变量中推断出来 , 这消除了对错误调用堆栈的任何假设

//bad
function foo(){}
//bad
const foo = function () {}
//good
const short = function longUnique () {}

7.2 将立即调用的函数表达式包装在括号中

(function (){
  console.log('Welcome to the Internet')
}()

7.3 切勿在非函数块(if、while 等)中声明函数。而是将函数分配给变量。浏览器将允许您执行此操作,但它们的解释各不相同

7.4 ECMA-262 将块定义为语句列表。函数声明不是语句

//bad
if (currentUser) {
  function test() {
    console.log('Mope. ')
  }
}

//good
let test
if (currentUser) {
  test = () => {
    consoe.log('Yup.')
  }
} 

7.5 永远不要命名参数参数。这将优先于提供给每个函数作用域的参数对象。

//bad
function foo (name,options,arguments) {}

//good
function foo (name,options,args) {}

7.6 永远不要使用参数,而是选择使用 rest 语法......代替

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

7.7 使用默认参数语法而不是改变函数参数

//really bad
//不!我们不应该改变函数参数。 
// 双重错误:如果 opts 为假,它将被设置为一个对象,该对象可能 
// 是你想要的,但它可能会引入微妙的错误
function handleThings (opts) {
  opts = opts || {}
}
//still bad
function handleThings (opts) {
  if (opts === void 0) {
    opts = {}
  }
}
//good 给予函数参数一个默认值
function handleThings (opts = {}) {
  
}

7.8 使用默认参数避免副作用

var b = 1;
//bad
function count (a = b++) {
  console.log(a)
}
count();//1
count();//2
//默认参数
count(3); //3
count(); //3

7.9 总是把默认参数放在最后

//bad
function handleThings(opts = {} , name){}
//good
function handleThings (name , opts = {}){}

7.10 切勿使用Function构造函数来创建新函数

//bad
var add = new Function('a','b','return a + b')
//still bad
var subtract = Function('a','b','return a -b')

7.11 函数前空格

//bad
const f = function(){}
const g = function (){}
const h = function() {}
//good
const x = function () {};
const y = function a() {};

7.12 永远不要改变参数

//bad
function f1 (obj) {
  obj.key = 1
}
//good
function f2 (obj) {
  const key = Object.prototype.hasOwnProperty.call(obj,'key') ? obj.key : 1
}

7.13 永远不要重新分配参数

//bad
//重新分配参数可能会导致意外行为,尤其是在访问参数对象时。它还可能导致优化问题,尤其是在 V8 中
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 使用...调用可变函数参数

//bad
const x = [1,2,3,4]
console.log.apply (console,x)
//good
const x = [1,2,3,4];
console.log(...x)
//bad
new (Function.prototype.bind.apply(Date,[null,2016,8,5]))
//good
new Date(...[2016,8,5])

7.15 具有多行签名或调用的函数应该像本指南中的所有其他多行列表一样缩进:每个项目单独在一行上,最后一个项目后面有逗号。

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

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

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

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

Arrow Functions

8.1 当您必须使用匿名函数时(如传递内联回调),请使用箭头函数表示法

// 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 如果函数体由返回一个没有副作用的表达式的单个语句组成,则省略大括号并使用隐式返回。否则,保留大括号并使用 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 + 1 }.`)
//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}))

// No implicit return with side effects
function foo(callback) {
  const val = callback();
  if (val === true) {
    // Do something if callback returns true
  }
}

let bool = false;

// bad
foo(() => bool = true);

// good
foo(() => {
  bool = true;
});

8.3 如果表达式跨越多行,请将其括在括号中以提高可读性

// 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为了清晰和一致性,始终在参数周围加上括号

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

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

// bad
[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!`
));

// 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 避免将箭头函数语法 (=>) 与比较运算符(<=、>=)混淆

// 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 使用隐式返回强制箭头函数体的位置

// bad
(foo) =>
  bar;

(foo) =>
  (bar);

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

Classes & Constructors

9.1 始终使用类 , 避免直接操作原型

//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 使用继承进行扩展

// 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以帮助方法链接 (链式调用 )

//bad
Jedi.prototype.jump = function () {
  this.jumping = true
  return true
}
Jedi.prototype.setHeight = function (height) {
  this.height = height
}
const luke = new Jedi();
luke.jump();
luke.setHeight(20)
//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方法成功工作并且无副作用

class Jedi {
  constructor (options = {}) {
    this.name = options.name || 'no name';
  }
  getName () {
    return this.name
  }
  toString () {
    return `Jedi - ${this.getName()}`
  }
}

9.5 如果未指定,则类具有默认构造函数。空构造函数或仅委托给父类的构造函数是不必要的

//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 避免重复的成员

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

9.7除非外部库或框架需要使用特定的非静态方法,否则类方法应使用此方法或将其制成静态方法。作为一个实例方法应该表明它根据接收者的属性表现不同

// bad
class Foo {
  bar() {
    console.log('bar');
  }
}

// good - this is used
class Foo {
  bar() {
    console.log(this.bar);
  }
}

// good - constructor is exempt
class Foo {
  constructor() {
    // ...
  }
}

// good - static methods aren't expected to use this
class Foo {
  static bar() {
    console.log('bar');
  }
}

Modules

10.1 始终在非标准模块系统上使用模块(导入/导出)。您始终可以转换为您喜欢的模块系统。

//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 不要使用通配符导入

//bad 
import * as AirbnbStyleGuide from './AirbnbStyleGuide'
//good
import AirbnbStyleGuide from './AirbnbStyleGuide'

10.3 不要直接从导入导出

有一种清晰的导入方式和一种清晰的导出方式可以使事情保持一致。

//bad
export { es6 as default } from './AirbnbStyleGuide'
//good
import { es6 } from './AirbnbStyleGuide'
export default es6

10.4 只从一个地方的路径导入

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

10.5 不要导出可变绑定

//bad
let foo = 3
export { foo }
//good
const foo = 3
export {foo}

10.6 在具有单个导出的模块中,更喜欢默认导出而不是命名导出

//bad
export function foo () {}
//good
export default function foo () {}

10.7 将所有导入放在非导入语句之上

//bad
import foo from 'foo';
foo.init();
import bar from 'bar';
//good
import foo from 'foo'
import bar from 'bar'
foo.init()

10.8 多行导入应该像多行数组和对象文字一样缩进

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

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

10.9 禁止在模块导入语句中使用 Webpack 加载程序语法

由于在导入中使用 Webpack 语法将代码耦合到模块捆绑器。更喜欢在 webpack.config.js 中使用加载器语法

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

10.10 不包含 JavaScript 文件扩展名

// bad
import foo from './foo.js';
import bar from './bar.jsx';
import baz from './baz/index.jsx';

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

Iterators and Generators

11.1 不要使用迭代器。更喜欢 JavaScript 的高阶函数,而不是像 for-in 或 for-of 这样的循环

const number = [1,2,3,4,5];
//bad
let sum = 0;
for (let num of number) {
  sum += num
}
sum === 15
//good
let sum = 0
number.forEach((num)=> {
  sum += num
})
sum === 15
//best
const sum = number.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
const increasedByOne = number.map((num )=>num + 1)

11.2 暂时不要使用生成器

11.3 如果必须使用生成器,或者如果您无视我们的建议,请确保它们的函数签名间隔正确。

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

// bad
const bar = function * () {
  // ...
};

// bad
const baz = function *() {
  // ...
};

// bad
const quux = function*() {
  // ...
};

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

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

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

// very bad
const wat = function
*
() {
  // ...
};

// good
function* foo() {
  // ...
}

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

Properties

12.1 访问属性时使用点表示法

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;

Variables

13.1 始终使用 const 或 let 来声明变量。不这样做会导致全局变量

// bad
superPower = new SuperPower();

// good
const superPower = new SuperPower();

13.2 每个变量或赋值使用一个 const 或 let 声明

// 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 将所有常量分组,然后将所有 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 在需要的地方分配变量,但将它们放在合理的位置。

// bad - 不必要的函数调用
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 ) );
  // let 关键字仅适用于变量 a;变量 b 和 c 变成全局变量
  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

// 同样适用于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 避免在赋值之前或之后使用换行符。如果您的赋值违反了 max-len,请将值括在括号中

// bad
const foo =
  superLongLongLongLongLongLongLongLongFunctionName();

// bad
const foo
  = 'superLongLongLongLongLongLongLongLongString';

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

// good
const foo = 'superLongLongLongLongLongLongLongLongString';

13.8 禁止未使用的变量


// bad

var some_unused_var = 42;

// 只写变量不被视为已使用
var y = 10;
y = 5;

// 对自身修改的读取不被视为已使用
var z = 0;
z = z + 1;

// 未使用的函数参数
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));

var { type, ...coords } = data;


Hoisting

14.1 var 声明被提升到它们最近的封闭函数作用域的顶部,它们的赋值没有。 const 和 let 声明有一个称为临时死区 (TDZ) 的新概念

//我们知道这行不通
function example() {
  console.log(notDefined); // => throws a ReferenceError
}
 //在你之后创建一个变量声明 引用变量将起作用,因为 变量提升。注:赋值  `true` 的值没有被提升。
function example() {
  console.log(declaredButNotAssigned); // => undefined
  var declaredButNotAssigned = true;
}
//解释器正在提升变量 声明到作用域的顶部 这意味着我们的示例可以重写为:
function example() {
  let declaredButNotAssigned;
  console.log(declaredButNotAssigned); // => undefined
  declaredButNotAssigned = true;
}

// using const and let
function example() {
  console.log(declaredButNotAssigned); // => throws a ReferenceError
  console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
  const declaredButNotAssigned = true;
}

14.2 匿名函数表达式会提升它们的变量名,但不会提升函数赋值

function example() {
  console.log(anonymous); // => undefined

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

  var anonymous = function () {
    console.log('anonymous function expression');
  };
}

14.3 命名函数表达式提升变量名,而不是函数名或函数体。

function example() {
  console.log(named); // => undefined

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

  superPower(); // => ReferenceError superPower is not defined

  var named = function superPower() {
    console.log('Flying');
  };
}

// the same is true when the function name
// is the same as the variable name.
function example() {
  console.log(named); // => undefined

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

  var named = function named() {
    console.log('named');
  };
}

14.4 函数声明提升它们的名称和函数体

function example() {
  superPower(); // => Flying

  function superPower() {
    console.log('Flying');
  }
}

Comparison Operators & Equality

15.1 在 == 和 != 上使用 === 和 !==

15.2 条件语句(如 if 语句)使用 ToBoolean 抽象方法强制计算其表达式

object => true undefined => false Null => false Boolean => bolean

+0、-0 或 NaN => false "" => false [] => true

15.3 对布尔值使用快捷方式,但对字符串和数字使用显式比较

// bad
if (isValid === true) {
  // ...
}

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

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

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

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

// good
if (collection.length > 0) {
  // ...
}

15.4 使用大括号在 case 和 default 子句中创建块,这些子句包含词法声明(例如 let、const、function 和 class)

// 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 三元不应该嵌套并且通常是单行表达式

// bad
const foo = maybe1 > maybe2
  ? "bar"
  : value1 > value2 ? "baz" : null;

// split into 2 separated ternary expressions
const maybeNull = value1 > value2 ? 'baz' : null;

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

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

15.7 避免不必要的三元语句

// 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 混合运算符时,将它们括在括号中。唯一的例外是标准算术运算符:+、- 和 **,因为它们的优先级被广泛理解。我们建议将 / 和 * 括在括号中,因为当它们混合时,它们的优先级可能不明确

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

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

// bad
// one may be confused into thinking (a || b) && c
if (a || b && c) {
  return d;
}

// bad
const bar = a + b / c * 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;

Blocks

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 和 else 的多行块,请将 else 与 if 块的右大括号放在同一行

// bad
if (test) {
  thing1();
  thing2();
}
else {
  thing3();
}

// good
if (test) {
  thing1();
  thing2();
} else {
  thing3();
}

16.3 如果 if 块总是执行 return 语句,则后续的 else 块是不必要的。在包含 return 的 if 块之后的 else if 块中的 return 可以分成多个 if 块

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

Control Statements

17.1 如果您的控制语句(if、while 等)变得太长或超过最大行长度,则可以将每个(分组)条件放入一个新行中。逻辑运算符应开始该行

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

Comments

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 将 // 用于单行注释。将单行注释放在注释主题上方的换行符上。在注释之前放置一个空行,除非它在块的第一行

// 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 为您的注释添加前缀有助于其他开发人员快速了解您是否指出需要重新审视的问题,或者您是否建议解决需要实施的问题。这些与常规注释不同,因为它们是可操作的。操作是 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;
  }
}

Whitespace

19.1 使用软制表符(空格字符)设置为 2 个空格

// bad
function foo() {
∙∙∙∙let name;
}

// bad
function bar() {
∙let name;
}

// good
function baz() {
∙∙let name;
}

19.2 在前导括号前放置 1 个空格

// 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 等)中的左括号前放置 1 个空格。在函数调用和声明中的参数列表和函数名称之间不要放置空格

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

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

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

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

19.4 用空格分隔运算符

// bad
const x=y+5;

// good
const x = y + 5;

19.5 使用单个换行符结束文件

// bad
import { es6 } from './AirbnbStyleGuide';
  // ...
export default es6;
// bad
import { es6 } from './AirbnbStyleGuide';
  // ...
export default es6;↵
↵
// good
import { es6 } from './AirbnbStyleGuide';
  // ...
export default es6;↵

19.6 在制作长方法链(超过 2 个方法链)时使用缩进。使用前导点,强调该行是方法调用,而不是新语句

// 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);
const svg = leds.enter().append('svg:svg');
svg.classed('led', true).attr('width', (radius + margin) * 2);
const g = svg.append('svg:g');
g.attr('transform', `translate(${radius + margin},${radius + margin})`).call(tron.led);

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
class Person {
  constructor(fullName, email, birthday) {
    this.fullName = fullName;


    this.email = email;


    this.setAge(birthday);
  }


  setAge(birthday) {
    const today = new Date();


    const age = this.getAge(today, birthday);


    this.age = age;
  }


  getAge(today, birthday) {
    // ..
  }
}

// good
class Person {
  constructor(fullName, email, birthday) {
    this.fullName = fullName;
    this.email = email;
    this.setAge(birthday);
  }

  setAge(birthday) {
    const today = new Date();
    const age = getAge(today, birthday);
    this.age = age;
  }

  getAge(today, birthday) {
    // ..
  }
}

19.10 不要在括号内添加空格

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

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

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

// good
if (foo) {
  console.log(foo);
}
// bad
const foo = [ 1, 2, 3 ];
console.log(foo[ 0 ]);

// good
const foo = [1, 2, 3];
console.log(foo[0]);

19.11 在花括号内添加空格

// bad
const foo = {clark: 'kent'};

// good
const foo = { clark: 'kent' };

19.12 避免代码行超过 100 个字符(包括空格)。注意:如上所述,长字符串不受此规则的约束,不应拆分

// bad
const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy;

// bad
$.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.'));

// good
const foo = jsonData
  && jsonData.foo
  && jsonData.foo.bar
  && jsonData.foo.bar.baz
  && jsonData.foo.bar.baz.quux
  && jsonData.foo.bar.baz.quux.xyzzy;

// good
$.ajax({
  method: 'POST',
  url: 'https://airbnb.com/',
  data: { name: 'John' },
})
  .done(() => console.log('Congratulations!'))
  .fail(() => console.log('You have failed this city.'));

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 强制计算属性括号内的间距

// 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 避免在函数及其调用之间使用空格

// bad
func ();

func
();

// good
func();

19.17 强制对象字面量属性中键和值之间的间距

// bad
var obj = { foo : 42 };
var obj2 = { foo:42 };

// good
var obj = { foo: 42 };

19.18 避免行尾的尾随空格

19.19 避免多个空行,文件末尾只允许一个换行符,文件开头避免一个换行符

// bad - multiple empty lines
var x = 1;


var y = 2;

// bad - 2+ newlines at end of file
var x = 1;
var y = 2;


// bad - 1+ newline(s) at beginning of file

var x = 1;
var y = 2;

// good
var x = 1;
var y = 2;


Commas

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 附加尾随逗号

这会导致更干净的 git 差异。此外,像 Babel 这样的转译器会删除转译后的代码中额外的尾随逗号,这意味着您不必担心旧浏览器中的尾随逗号问题。

 // bad - git diff without trailing comma
const hero = {
     firstName: 'Florence',
-    lastName: 'Nightingale'
+    lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing']
};

// good - git diff with trailing comma
const hero = {
     firstName: 'Florence',
     lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing'],
};
// bad
const hero = {
  firstName: 'Dana',
  lastName: 'Scully'
};

const heroes = [
  'Batman',
  'Superman'
];

// good
const hero = {
  firstName: 'Dana',
  lastName: 'Scully',
};

const heroes = [
  'Batman',
  'Superman',
];

// bad
function createHero(
  firstName,
  lastName,
  inventorOf
) {
  // does nothing
}

// good
function createHero(
  firstName,
  lastName,
  inventorOf,
) {
  // does nothing
}

// good 请注意,逗号不能出现在“rest”元素之后
function createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
) {
  // does nothing
}

// bad
createHero(
  firstName,
  lastName,
  inventorOf
);

// good
createHero(
  firstName,
  lastName,
  inventorOf,
);

// good 请注意,逗号不能出现在“rest”元素之后
createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
);
 // bad - git diff without trailing comma
const hero = {
     firstName: 'Florence',
-    lastName: 'Nightingale'
+    lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing']
};

// good - git diff with trailing comma
const hero = {
     firstName: 'Florence',
     lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing'],
};
// bad
const hero = {
  firstName: 'Dana',
  lastName: 'Scully'
};

const heroes = [
  'Batman',
  'Superman'
];

// good
const hero = {
  firstName: 'Dana',
  lastName: 'Scully',
};

const heroes = [
  'Batman',
  'Superman',
];

// bad
function createHero(
  firstName,
  lastName,
  inventorOf
) {
  // does nothing
}

// good
function createHero(
  firstName,
  lastName,
  inventorOf,
) {
  // does nothing
}

// good 请注意,逗号不能出现在“rest”元素之后
function createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
) {
  // does nothing
}

// bad
createHero(
  firstName,
  lastName,
  inventorOf
);

// good
createHero(
  firstName,
  lastName,
  inventorOf,
);

// good 请注意,逗号不能出现在“rest”元素之后
createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
);
 // bad - git diff without trailing comma
const hero = {
     firstName: 'Florence',
-    lastName: 'Nightingale'
+    lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing']
};

// good - git diff with trailing comma
const hero = {
     firstName: 'Florence',
     lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing'],
};
// bad
const hero = {
  firstName: 'Dana',
  lastName: 'Scully'
};

const heroes = [
  'Batman',
  'Superman'
];

// good
const hero = {
  firstName: 'Dana',
  lastName: 'Scully',
};

const heroes = [
  'Batman',
  'Superman',
];

// bad
function createHero(
  firstName,
  lastName,
  inventorOf
) {
  // does nothing
}

// good
function createHero(
  firstName,
  lastName,
  inventorOf,
) {
  // does nothing
}

// good 请注意,逗号不能出现在“rest”元素之后
function createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
) {
  // does nothing
}

// bad
createHero(
  firstName,
  lastName,
  inventorOf
);

// good
createHero(
  firstName,
  lastName,
  inventorOf,
);

// good 请注意,逗号不能出现在“rest”元素之后
createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
);
 // bad - git diff without trailing comma
const hero = {
     firstName: 'Florence',
-    lastName: 'Nightingale'
+    lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing']
};

// good - git diff with trailing comma
const hero = {
     firstName: 'Florence',
     lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing'],
};
// bad
const hero = {
  firstName: 'Dana',
  lastName: 'Scully'
};

const heroes = [
  'Batman',
  'Superman'
];

// good
const hero = {
  firstName: 'Dana',
  lastName: 'Scully',
};

const heroes = [
  'Batman',
  'Superman',
];

// bad
function createHero(
  firstName,
  lastName,
  inventorOf
) {
  // does nothing
}

// good
function createHero(
  firstName,
  lastName,
  inventorOf,
) {
  // does nothing
}

// good 请注意,逗号不能出现在“rest”元素之后
function createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
) {
  // does nothing
}

// bad
createHero(
  firstName,
  lastName,
  inventorOf
);

// good
createHero(
  firstName,
  lastName,
  inventorOf,
);

// good 请注意,逗号不能出现在“rest”元素之后
createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
);
 // bad - git diff without trailing comma
const hero = {
     firstName: 'Florence',
-    lastName: 'Nightingale'
+    lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing']
};

// good - git diff with trailing comma
const hero = {
     firstName: 'Florence',
     lastName: 'Nightingale',
+    inventorOf: ['coxcomb chart', 'modern nursing'],
};
// bad
const hero = {
  firstName: 'Dana',
  lastName: 'Scully'
};

const heroes = [
  'Batman',
  'Superman'
];

// good
const hero = {
  firstName: 'Dana',
  lastName: 'Scully',
};

const heroes = [
  'Batman',
  'Superman',
];

// bad
function createHero(
  firstName,
  lastName,
  inventorOf
) {
  // does nothing
}

// good
function createHero(
  firstName,
  lastName,
  inventorOf,
) {
  // does nothing
}

// good 请注意,逗号不能出现在“rest”元素之后
function createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
) {
  // does nothing
}

// bad
createHero(
  firstName,
  lastName,
  inventorOf
);

// good
createHero(
  firstName,
  lastName,
  inventorOf,
);

// good 请注意,逗号不能出现在“rest”元素之后
createHero(
  firstName,
  lastName,
  inventorOf,
  ...heroArgs
);

Semicolons

21.1

// bad - raises exception
const luke = {}
const leia = {}
[luke, leia].forEach((jedi) => jedi.father = 'vader')

// bad - raises exception
const reaction = "No! That’s impossible!"
(async function meanwhileOnTheFalcon() {
  // handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
  // ...
}())

// bad - returns `undefined` instead of the value on the next line - always happens when `return` is on a line by itself because of ASI!
function foo() {
  return
    'search your feelings, you know it to be foo'
}

// good
const luke = {};
const leia = {};
[luke, leia].forEach((jedi) => {
  jedi.father = 'vader';
});

// good
const reaction = "No! That’s impossible!";
(async function meanwhileOnTheFalcon() {
  // handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
  // ...
}());

// good
function foo() {
  return 'search your feelings, you know it to be foo';
}

Type Casting & Coercion

22.1 在语句的开头执行类型强制

22.2 字符串

//  => this.reviewScore = 0
//bad
const totalScore = new String(this.reviewScore) //导致创建的totalScore是object类型而不是string类型
//bad
const totalScore = this.reviewScore + '' //调用 this.reviewScore.valueOf()
//bad
const totalScore = this.reviewScore.toString() // 不能保证一定的返回字符串
//good
const totalScore = String(this.reviewScore)

22.3 使用Number进行类型转换 , 使用parseInt始终使用基数来解析字符串

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 如果出于某种原因,您正在做一些疯狂的事情,而 parseInt 是您的瓶颈,并且出于性能原因需要使用 Bitshift,请添加注释,解释原因和您在做什么

// good
/**
 * parseInt was the reason my code was slow.
 * Bitshifting the String to coerce it to a
 * Number made it a lot faster.
 */
const val = inputValue >> 0;

22.5 注意:使用位移操作时要小心。数字表示为 64 位值,但位移操作始终返回 32 位整数(来源)。对于大于 32 位的整数值,Bitshift 可能会导致意外行为。讨论。最大的有符号 32 位整数是 2,147,483,647

2147483647 >> 0; // => 2147483647
2147483648 >> 0; // => -2147483648
2147483649 >> 0; // => -2147483647

22.6 Boolean

const age = 0
//bad
const hasAge = new Boolean(age);
//good
const hasAge = Boolean(age);
//best
const hasAge = !!age

Naming Conventions

23.1 避免使用单字母名称。用你的名字来描述

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

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

23.2 命名对象、函数和实例时使用驼峰命名法。

// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}

// good
const thisIsMyObject = {};
function thisIsMyFunction() {}

23.3 仅在命名构造函数或类时使用 PascalCase

// 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',
});

23.4 不要使用尾随或前导下划线

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

//good
this.firstName = 'Panda'

// 好 , 在weakMaps 可用的环境中

const firstName = new WeakMap();
firstNames.set(this,'Panda')

23.5 不要保存对this的引用 , 使用箭头函数或是Function

// 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 基本文件名应与其默认导出的名称完全匹配

//file 1 contents
class CheakBox {
  //...
}
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';
import FortyTwo from './FortyTwo';
import InsideDirectory from './InsideDirectory'

//bad
import CheckBox from './cheak_box';
import forty_two from './forty_two';
import inside_directory from './inside_directory';
import index from './inside_directory/index';
import insideDirectory from './insideDirectory/index'

//good
import CheckBox from './CheckBox'
import fortyTwo from './fortTwo'
import insideDirectory from './insideDirectory'

23.7 在导出默认函数时使用驼峰式命名法 , 文件名应该与函数名称相同

function makeStyleGuide () {
  //...
}
export default makeStyleGuide;

23.8 导出构造函数/类/单例/函数库/裸对象时使用 PascalCase

const AirbnbStyleGuide = {
  es6: {
    
  },
}
export default AirbnbStyleGuide;

23.9 首字母缩略词和首字母缩写词应始终全部大写或全部小写

//bad
import SmsContainer from './container/SmsContainer'
//bad
const HttpRequests = [
  //...
  ]

//good
import SMSContainer from './container/SMSContainer'
//good
const HTTPRequests = []
//also good
const httpRequests = []
//best
import TextMessageContainer from './container/TextMessageContainer';
//best
const requests = []