# AirbnbJavaScript风格指南

#### 作者：高天阳

#### 邮箱：<13683265113@163.com>

```
更改历史

* 2018-09-14    高天阳    更新目录
* 2017-11-14    高天阳    初始化文档
```

## 1 目录

1. [类型](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#类型)
2. [对象](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#对象)
3. [数组](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#数组)
4. [字符串](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#字符串)
5. [函数](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#函数)
6. [属性](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#属性)
7. [变量](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#变量)
8. [提升](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#提升)
9. [比较运算符和等号](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#比较运算符和等号)
10. [块](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#块)
11. [注释](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#注释)
12. [空白](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#空白)
13. [逗号](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#逗号)
14. [分号](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#分号)
15. [类型转化](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#类型转化)
16. [命名规则](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#命名规则)
17. [存取器](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#存取器)
18. [构造函数](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#构造函数)
19. [事件](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#事件)
20. [模块](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#模块)
21. [jQuery的](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#jQuery的)
22. [ECMAScript 5兼容性](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#ECMAScript%205兼容性)
23. [测试](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#测试)
24. [性能](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#性能)
25. [资源](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#资源)
26. [谁在使用](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#谁在使用)
27. [翻译](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#翻译)
28. [JavaScript风格指南说明](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#JavaScript风格指南说明)
29. [与我们讨论JavaScript](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#与我们讨论JavaScript)
30. [贡献者](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#贡献者)
31. [许可](https://mitudegaoyang.gitbook.io/j/codereview/pages/-MU324eBsXcCyNqRrtxw#许可)

## 2 正文

### 2.1 类型 <a href="#lei-xing" id="lei-xing"></a>

* **原始值**：存取直接作用于它自身。
  * string
  * number
  * boolean
  * null
  * undefined

```
var foo = 1;
var bar = foo;

bar = 9;

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

* **复杂类型**：存在时作用于它自身值的引用。
  * object
  * array
  * function

```
var foo = [1, 2];
var bar = foo;

bar[0] = 9;

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

### 2.2 对象 <a href="#dui-xiang" id="dui-xiang"></a>

* 使用直接量创建对象。

```
// bad
var item = new Object();

// good
var item = {};
```

* 不要使用[保留字](http://es5.github.io/#x7.6.1)作为键名，它们在IE8下不工作。[更多信息](https://github.com/airbnb/javascript/issues/61)。

```
// bad
var superman = {
  default: { clark: 'kent' },
  private: true
};

// good
var superman = {
  defaults: { clark: 'kent' },
  hidden: true
};
```

* 使用同义词替换需要使用的保留字。

```
// bad
var superman = {
  class: 'alien'
};

// bad
var superman = {
  klass: 'alien'
};

// good
var superman = {
  type: 'alien'
};
```

### 2.3 数组 <a href="#shu-zu" id="shu-zu"></a>

* 使用直接量创建数组。

```
// bad
var items = new Array();

// good
var items = [];
```

* 向数组增加元素时使用Array＃push来替代直接赋值。

javascript

var someStack = \[];

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

// good
someStack.push('abracadabra');
```

* 当你需要拷贝数组时，使用Array＃[slice。jsPerf](https://jsperf.com/converting-arguments-to-an-array/7)

```
var len = items.length;
var itemsCopy = [];
var i;

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

// good
itemsCopy = items.slice();
```

> Demo

```
// bad
var a = [1,2,3];
var b = a;

console.log(a);// => [1,2,3]
console.log(b);// => [1,2,3]

a[0]=4;

console.log(a);// => [4,2,3]
console.log(b);// => [4,2,3]
```

```
// bad
var a = [1,2,3];
var b = [];

console.log(a);// => [1,2,3]
console.log(b);// => []

for(var i=0; i<a.length; i++){b[i]=a[i]}

console.log(a);// => [1,2,3]
console.log(b);// => [1,2,3]

a[0]=4;

console.log(a);// => [4,2,3]
console.log(b);// => [1,2,3]
```

```
// good
var a = [1,2,3];
var b = a.slice();

console.log(a);// => [1,2,3]
console.log(b);// => [1,2,3]

a[0]=4;

console.log(a);// => [4,2,3]
console.log(b);// => [1,2,3]
```

* 使用[Array＃slice](https://www.cnblogs.com/dingxiaoyue/p/4948166.html)将类数组对象转换成数组。

```
function trigger() {
  var args = Array.prototype.slice.call(arguments);
  ...
}
```

> Demo

```
function trigger() {
  var args = Array.prototype.slice.call(arguments);
  return args
}
function trigger2() {
  return arguments
}

// bad
a = trigger2('a','b','c','d') // 此时a为类数组对象
a.push('e');// => Uncaught TypeError: a.push is not a function

// good
a = trigger('a','b','c','d') // 此时a为数组对象
a.push('e');
console.log(a);// => ["a", "b", "c", "d", "e"]
```

### 2.4 字符串 <a href="#zi-fu-chuan" id="zi-fu-chuan"></a>

* 使用单引号''包裹字符串。

```
// bad
var name = "Bob Parr";

// good
var name = 'Bob Parr';

// bad
var fullName = "Bob " + this.lastName;

// good
var fullName = 'Bob ' + this.lastName;
```

* 超过100个字符的字符串应该使用连接符写成多行。
* 注：若过度使用，通过连接符连接的长字符串可能会影响性能。[jsPerf](https://jsperf.com/ya-string-concat)＆[讨论](https://github.com/airbnb/javascript/issues/40)。

```
// bad
var 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
var 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
var 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.';
```

* 程序化生成的字符串使用Array＃join连接而不是使用连接符。尤其是IE下：[jsPerf](http://jsperf.com/string-vs-array-concat/2)。

```
var items;
var messages;
var length;
var i;

messages = [{
  state: 'success',
  message: 'This one worked.'
}, {
  state: 'success',
  message: 'This one worked as well.'
}, {
  state: 'error',
  message: 'This one did not work.'
}];

length = messages.length;

// bad
function inbox(messages) {
  items = '<ul>';

  for (i = 0; i < length; i++) {
    items += '<li>' + messages[i].message + '</li>';
  }

  return items + '</ul>';
}

// good
function inbox(messages) {
  items = [];

  for (i = 0; i < length; i++) {
    // use direct assignment in this case because we're micro-optimizing.
    items[i] = '<li>' + messages[i].message + '</li>';
  }

  return '<ul>' + items.join('') + '</ul>';
}
```

### 2.5 函数 <a href="#han-shu" id="han-shu"></a>

* 函数表达式：

```
// 匿名函数表达式
var anonymous = function() {
  return true;
};

// 命名函数表达式
var named = function named() {
  return true;
};

// 立即调用的函数表达式（IIFE）
(function () {
  console.log('Welcome to the Internet. Please follow me.');
}());
```

* 永远不要在一个非函数代码块（if，while等）中声明一个函数，把那个函数赋予给一个变量。但是它们的解析表现不一致。
* **注意： ECMA-262**把`块`定义为一组语句。函数声明不是语句。[阅读对ECMA-262这个问题的说明](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf#page=97)。

```
// bad
if (currentUser) {
  function test() {
    console.log('Nope.');
  }
}

// good
var test;
if (currentUser) {
  test = function test() {
    console.log('Yup.');
  };
}
```

* 永远不要把参数命名为`arguments`。将这取代函数作用英文域内的`arguments`对象。

```
// bad
function nope(name, options, arguments) {
  // ...stuff...
}

// good
function yup(name, options, args) {
  // ...stuff...
}
```

### 2.6 属性 <a href="#shu-xing" id="shu-xing"></a>

* 使用`.`来访问对象的属性。

```
var luke = {
  jedi: true,
  age: 28
};

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

// good
var isJedi = luke.jedi;
```

* 当通过变量访问属性时使用中括号`[]`。

```
var luke = {
  jedi: true,
  age: 28
};

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

var isJedi = getProp('jedi');
```

### 2.7 变量 <a href="#bian-liang" id="bian-liang"></a>

* 使用总是`var`来声明变量。不这么做将导致产生全局变量。我们要避免污染全局命名空间。

```
// bad
superPower = new SuperPower();

// good
var superPower = new SuperPower();
```

* 使用`var`声明每一个变量。

这样做的好处是增加新变量将变的更加容易，你而且永远不用再担心调换错`;`跟`,`。

```
// bad
var items = getItems(),
    goSportsTeam = true,
    dragonball = 'z';

// bad
// （跟上面的代码比较一下，看看哪里错了）
var items = getItems(),
    goSportsTeam = true;
    dragonball = 'z';

// good
var items = getItems();
var goSportsTeam = true;
var dragonball = 'z';
```

* 最后再声明未赋值的变量。当你需要引用前面的变量赋值时这将变的很有用。

```
// bad
var i, len, dragonball,
    items = getItems(),
    goSportsTeam = true;

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

// good
var items = getItems();
var goSportsTeam = true;
var dragonball;
var length;
var i;
```

* 在作用域顶部声明变量。这将帮你避免变量声明提升相关的问题。

```
// bad
function () {
  test();
  console.log('doing stuff..');

  //..other stuff..

  var name = getName();

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

  return name;
}

// good
function () {
  var name = getName();

  test();
  console.log('doing stuff..');

  //..other stuff..

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

  return name;
}

// bad - 不必要的函数调用
function () {
  var name = getName();

  if (!arguments.length) {
    return false;
  }

  this.setFirstName(name);

  return true;
}

// good
function () {
  var name;

  if (!arguments.length) {
    return false;
  }

  name = getName();
  this.setFirstName(name);

  return true;
}
```

* \`\`\`

```
-
```

\`\`\`

> 难点：最佳实践，超出于示例，应该归纳总结出积累的技巧。

## 3 同类技术对比

> 难点：归纳比对项

## 参考资料

* [大道至简非简博客](http://www.jianshu.com/p/86331bdbf970)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mitudegaoyang.gitbook.io/j/codereview/airbnbjavascript.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
