![Gitter](https://badges.gitter.im/Join Chat.svg)
一份彙整了在 JavasScript 中被普遍使用的風格指南。
翻譯自 Airbnb JavaScript Style Guide 。
- 資料型態
- 物件
- 陣列
- 字串
- 函式
- 屬性
- 變數
- 提升
- 條件式與等號
- 區塊
- 註解
- 空格
- 逗號
- 分號
- 型別轉換
- 命名規則
- 存取器
- 建構子
- 事件
- 模組
- jQuery
- ECMAScript 5 相容性
- 測試
- 效能
- 資源
- 誰在使用
- 翻譯
- JavaScript 風格指南
- 和我們討論 Javascript
- 貢獻者
- 授權許可
-
基本: 你可以直接存取基本資料型態。
字串
數字
布林
null
undefined
var foo = 1; var bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
-
複合: 你需要透過引用的方式存取複合資料型態。
物件
陣列
函式
var foo = [1, 2]; var bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
-
使用簡潔的語法建立物件。
// bad var item = new Object(); // good var item = {};
-
// 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' };
-
使用簡潔的語法建立陣列。
// bad var items = new Array(); // good var items = [];
-
如果你不知道陣列的長度請使用 Array#push。
var someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
-
如果你要複製一個陣列請使用 Array#slice。jsPerf
var len = items.length; var itemsCopy = []; var i; // bad for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good itemsCopy = items.slice();
-
如果要轉換一個像陣列的物件至陣列,可以使用 Array#slice。
function trigger() { var args = Array.prototype.slice.call(arguments); ... }
-
字串請使用單引號
''
。// bad var name = "Bob Parr"; // good var name = 'Bob Parr'; // bad var fullName = "Bob " + this.lastName; // good var fullName = 'Bob ' + this.lastName;
-
如果字串超過 100 個字元,請使用字串連接符號換行。
-
注意: 過度的長字串連接可能會影響效能 jsPerf 與討論串。
// 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。
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++) { // 在這個狀況時我們可以直接賦值來稍微最佳化程式 items[i] = '<li>' + messages[i].message + '</li>'; } return '<ul>' + items.join('') + '</ul>'; }
-
函式表達式:
// 匿名函式 var anonymous = function() { return true; }; // 命名函式 var named = function named() { return true; }; // 立即函式 (immediately-invoked function expression, IIFE) (function() { console.log('Welcome to the Internet. Please follow me.'); })();
-
絕對不要在非函式的區塊(if, while, 等等)宣告函式,瀏覽器或許會允許你這麼做,但不同瀏覽器產生的結果可能會不同。你可以將函式賦予一個區塊外的變數解決這個問題。
-
**注意:**ECMA-262 將
區塊
定義為陳述式,函式宣告則不是陳述式。 閱讀 ECMA-262 關於這個問題的說明。// 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... }
-
使用點
.
來存取屬性。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');
-
為了避免污染全域的命名空間,請使用
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; }
-
變數宣告可以被提升至該作用域的最頂層,但賦予的值並不會。
// 我們知道這樣是行不通的 // (假設沒有名為 notDefined 的全域變數) function example() { console.log(notDefined); // => throws a ReferenceError } // 由於變數提升的關係, // 你在引用變數後再宣告變數是行得通的。 // 注:賦予給變數的 `true` 並不會被提升。 function example() { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; } // 直譯器會將宣告的變數提升至作用域的最頂層, // 表示我們可以將這個例子改寫成以下: function example() { var declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; }
-
賦予匿名函式的變數會被提升,但函式內容並不會。
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function() { console.log('anonymous function expression'); }; }
-
賦予命名函式的變數會被提升,但函式內容及函式名稱並不會。
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'); }; } // 當函式名稱和變數名稱相同時也是如此。 function example() { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); } }
-
宣告函式的名稱及函式內容都會被提升。
function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } }
-
想瞭解更多訊息,請參考 Ben Cherry 的 JavaScript Scoping & Hoisting。
-
請使用
===
和!==
,別使用==
及!=
。 -
像是
if
的條件語法內會使用ToBoolean
的抽象方法強轉類型,並遵循以下規範:- 物件 轉換為 true
- Undefined 轉換為 false
- Null 轉換為 false
- 布林 轉換為 該布林值
- 數字 如果是 +0, -0, 或 NaN 則轉換為 false ,其他的皆為 true
- 字串 如果是空字串
''
則轉換為 false ,其他的皆為 true
if ([0]) { // true // 陣列為一個物件,所以轉換為 true }
-
使用快速的方式。
// bad if (name !== '') { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... }
-
想瞭解更多訊息請參考 Angus Croll 的 Truth Equality and JavaScript。
-
多行區塊請使用花括號括起來。
// bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function() { return false; } // good function() { return false; }
- 如果你使用
if
及else
的多行區塊,請將else
放在if
區塊的結尾花括號之後。
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
- 如果你使用
-
多行註解請使用
/** ... */
,包含描述,指定類型以及參數值還有回傳值。// bad // make() 根據傳入的 tag 名稱回傳一個新的元件 // // @param {String} tag // @return {Element} element function make(tag) { // ...stuff... return element; } // good /** * make() 根據傳入的 tag 名稱回傳一個新的元件 * * @param {String} tag * @return {Element} element */ function make(tag) { // ...stuff... return element; }
-
單行註解請使用
//
,在欲註解的地方上方進行當行註解,並在註解前空一格。// bad var active = true; // 當目前分頁 // good // 當目前分頁 var active = true; // bad function getType() { console.log('fetching type...'); // 設定預設的類型為 'no type' var type = this._type || 'no type'; return type; } // good function getType() { console.log('fetching type...'); // 設定預設的類型為 'no type' var type = this._type || 'no type'; return type; }
-
在註解前方加上
FIXME
或TODO
可以幫助其他開發人員快速瞭解這是一個需要重新討論的問題,或是一個等待解決的問題。和一般的註解不同,他們是可被執行的。對應的動作為FIXME -- 重新討論並解決
或TODO -- 必須執行
. -
使用
// FIXME:
標注問題。function Calculator() { // FIXME: 不該在這使用全域變數 total = 0; return this; }
-
使用
// TODO:
標注問題的解決方式function Calculator() { // TODO: total 應該可被傳入的參數所修改 this.total = 0; return this; }
**[⬆ 回到頂端](#table-of-contents)**
<a name="whitespace"></a>
## 空格
- 將 Tab 設定為兩個空格。
```javascript
// bad
function() {
∙∙∙∙var name;
}
// bad
function() {
∙var name;
}
// good
function() {
∙∙var name;
}
```
- 在花括號前加一個空格。
```javascript
// 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'
});
```
- 在控制流程的語句(`if`, `while` 等等。)的左括號前加上一個空格。宣告的函式和傳入的變數間則沒有空格。
```javascript
// bad
if(isJedi) {
fight ();
}
// good
if (isJedi) {
fight();
}
// bad
function fight () {
console.log ('Swooosh!');
}
// good
function fight() {
console.log('Swooosh!');
}
```
- 將運算元用空格隔開。
```javascript
// bad
var x=y+5;
// good
var x = y + 5;
```
- 在檔案的最尾端加上一行空白行。
```javascript
// bad
(function(global) {
// ...stuff...
})(this);
```
```javascript
// bad
(function(global) {
// ...stuff...
})(this);↵
↵
```
```javascript
// good
(function(global) {
// ...stuff...
})(this);↵
```
- 當多個方法連接時請換行縮排,利用前面的 `.` 強調該行是呼叫方法,而不是一個新的宣告。
```javascript
// 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
var 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
var 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);
```
- 區塊的結束和下個語法間加上空行。
```javascript
// bad
if (foo) {
return bar;
}
return baz;
// good
if (foo) {
return bar;
}
return baz;
// bad
var obj = {
foo: function() {
},
bar: function() {
}
};
return obj;
// good
var obj = {
foo: function() {
},
bar: function() {
}
};
return obj;
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="commas"></a>
## 逗號
- 不要將逗號放在前方。
```javascript
// bad
var story = [
once
, upon
, aTime
];
// good
var story = [
once,
upon,
aTime
];
// bad
var hero = {
firstName: 'Bob'
, lastName: 'Parr'
, heroName: 'Mr. Incredible'
, superPower: 'strength'
};
// good
var hero = {
firstName: 'Bob',
lastName: 'Parr',
heroName: 'Mr. Incredible',
superPower: 'strength'
};
```
- 多餘的逗號:**Nope.** 在 IE6/7 及 IE9 的相容性模式中,多餘的逗號可能會產生問題。另外,在 ES3 的一些實現方式上會多計算陣列的長度,不過在 ES5 中已經被修正了([來源](http://es5.github.io/#D)):
> Edition 5 clarifies the fact that a trailing comma at the end of an ArrayInitialiser does not add to the length of the array. This is not a semantic change from Edition 3 but some implementations may have previously misinterpreted this.
```javascript
// bad
var hero = {
firstName: 'Kevin',
lastName: 'Flynn',
};
var heroes = [
'Batman',
'Superman',
];
// good
var hero = {
firstName: 'Kevin',
lastName: 'Flynn'
};
var heroes = [
'Batman',
'Superman'
];
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="semicolons"></a>
## 分號
- 句尾請加分號。
```javascript
// bad
(function() {
var name = 'Skywalker'
return name
})()
// good
(function() {
var name = 'Skywalker';
return name;
})();
// good (防止當兩個檔案含有立即函式需要合併時,函式被當成參數處理)
;(function() {
var name = 'Skywalker';
return name;
})();
```
[瞭解更多](http://stackoverflow.com/a/7365214/1712802).
**[⬆ 回到頂端](#table-of-contents)**
<a name="type-casting--coercion"></a>
## 型別轉換
- 在開頭的宣告進行強制型別轉換。
- 字串:
```javascript
// => this.reviewScore = 9;
// bad
var totalScore = this.reviewScore + '';
// good
var totalScore = '' + this.reviewScore;
// bad
var totalScore = '' + this.reviewScore + ' total score';
// good
var totalScore = this.reviewScore + ' total score';
```
- 對數字使用 `parseInt` 轉換,並帶上型別轉換的基數。
```javascript
var inputValue = '4';
// bad
var val = new Number(inputValue);
// bad
var val = +inputValue;
// bad
var val = inputValue >> 0;
// bad
var val = parseInt(inputValue);
// good
var val = Number(inputValue);
// good
var val = parseInt(inputValue, 10);
```
- 如果你因為某個原因在做些瘋狂的事情,但是 `parseInt` 是你的瓶頸,所以你對於[性能方面的原因](http://jsperf.com/coercion-vs-casting/3)而必須使用位元右移,請留下評論並解釋為什麼使用,及你做了哪些事情。
```javascript
// good
/**
* 使用 parseInt 導致我的程式變慢,改成使用
* 位元右移強制將字串轉為數字加快了他的速度。
*/
var val = inputValue >> 0;
```
- **注意:**使用位元轉換時請小心,數字為 [64 位元數值](http://es5.github.io/#x4.3.19),但是使用位元轉換時則會回傳一個 32 位元的整數 ([來源](http://es5.github.io/#x11.7)),這會導致大於 32 位元的數值產生異常[討論串](https://github.com/airbnb/javascript/issues/109),32 位元的整數最大值為 2,147,483,647:
```javascript
2147483647 >> 0 //=> 2147483647
2147483648 >> 0 //=> -2147483648
2147483649 >> 0 //=> -2147483647
```
- 布林:
```javascript
var age = 0;
// bad
var hasAge = new Boolean(age);
// good
var hasAge = Boolean(age);
// good
var hasAge = !!age;
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="naming-conventions"></a>
## 命名規則
- 避免使用單一字母的名稱,讓你的名稱有解釋的含義。
```javascript
// bad
function q() {
// ...stuff...
}
// good
function query() {
// ..stuff..
}
```
- 使用駝峰式大小寫命名物件,函式及實例。
```javascript
// bad
var OBJEcttsssss = {};
var this_is_my_object = {};
var o = {};
function c() {}
// good
var thisIsMyObject = {};
function thisIsMyFunction() {}
```
- 使用帕斯卡命名法來命名建構函式或類別。
```javascript
// bad
function user(options) {
this.name = options.name;
}
var bad = new user({
name: 'nope'
});
// good
function User(options) {
this.name = options.name;
}
var good = new User({
name: 'yup'
});
```
- 命名私有屬性時請在前面加底線 `_`。
```javascript
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// good
this._firstName = 'Panda';
```
- 要保留對 `this` 的使用時請用 `_this` 取代。
```javascript
// bad
function() {
var self = this;
return function() {
console.log(self);
};
}
// bad
function() {
var that = this;
return function() {
console.log(that);
};
}
// good
function() {
var _this = this;
return function() {
console.log(_this);
};
}
```
- 將你的函式命名,這對於在做堆疊追蹤時相當有幫助。
```javascript
// bad
var log = function(msg) {
console.log(msg);
};
// good
var log = function log(msg) {
console.log(msg);
};
```
- **注意:**IE8 及 IE8 以下對於命名函式有獨到見解。更多的訊息在 [http://kangax.github.io/nfe/](http://kangax.github.io/nfe/)。
- 如果你的檔案只有輸出一個類別,你的檔案名稱必須和你的類別名稱相同。
```javascript
// 檔案內容
class CheckBox {
// ...
}
module.exports = CheckBox;
// 在其他的檔案
// bad
var CheckBox = require('./checkBox');
// bad
var CheckBox = require('./check_box');
// good
var CheckBox = require('./CheckBox');
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="accessors"></a>
## 存取器
- 存取器不是必須的。
- 如果你要建立一個存取器,請使用 getVal() 及 setVal('hello')。
```javascript
// bad
dragon.age();
// good
dragon.getAge();
// bad
dragon.age(25);
// good
dragon.setAge(25);
```
- 如果屬性是布林,請使用 isVal() 或 hasVal()。
```javascript
// bad
if (!dragon.age()) {
return false;
}
// good
if (!dragon.hasAge()) {
return false;
}
```
- 可以建立 get() 及 set() 函式,但請保持一致。
```javascript
function Jedi(options) {
options || (options = {});
var lightsaber = options.lightsaber || 'blue';
this.set('lightsaber', lightsaber);
}
Jedi.prototype.set = function(key, val) {
this[key] = val;
};
Jedi.prototype.get = function(key) {
return this[key];
};
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="constructors"></a>
## 建構子
- 將方法分配給物件原型,而不是用新的物件覆蓋掉原型,否則會導致繼承出現問題:重置原型時你會覆蓋原有的原型。
```javascript
function Jedi() {
console.log('new jedi');
}
// bad
Jedi.prototype = {
fight: function fight() {
console.log('fighting');
},
block: function block() {
console.log('blocking');
}
};
// good
Jedi.prototype.fight = function fight() {
console.log('fighting');
};
Jedi.prototype.block = function block() {
console.log('blocking');
};
```
- 方法可以回傳 `this` 幫助方法鏈接。
```javascript
// bad
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined
// good
Jedi.prototype.jump = function() {
this.jumping = true;
return this;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
return this;
};
var luke = new Jedi();
luke.jump()
.setHeight(20);
```
- 可以寫一個 toString() 的方法,但是請確保他可以正常執行且沒有函式副作用。
```javascript
function Jedi(options) {
options || (options = {});
this.name = options.name || 'no name';
}
Jedi.prototype.getName = function getName() {
return this.name;
};
Jedi.prototype.toString = function toString() {
return 'Jedi - ' + this.getName();
};
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="events"></a>
## 事件
- 當需要對事件傳入資料時(不論是 DOM 事件或是其他私有事件),請傳入物件替代單一的資料。這樣可以使之後的開發人員直接加入其他的資料到事件裡,而不需更新該事件的處理器。例如,比較不好的做法:
```js
// bad
$(this).trigger('listingUpdated', listing.id);
...
$(this).on('listingUpdated', function(e, listingId) {
// do something with listingId
});
```
更好的做法:
```js
// good
$(this).trigger('listingUpdated', { listingId : listing.id });
...
$(this).on('listingUpdated', function(e, data) {
// do something with data.listingId
});
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="modules"></a>
## 模組
- 模組的開頭必須以 `!` 開頭, 這樣可以確保前一模組結尾忘記加分號時在合併後不會出現錯誤。[說明](https://github.com/airbnb/javascript/issues/44#issuecomment-13063933)
- 命名方式請使用駝峰式大小寫,並存在同名的資料夾下,導出時的名稱也必須一致。
- 加入一個名稱為 `noConflict()` 方法來設置導出時的模組為前一個版本,並將他回傳。
- 記得在模組的最頂端加上 `'use strict';` 。
```javascript
// fancyInput/fancyInput.js
!function(global) {
'use strict';
var previousFancyInput = global.FancyInput;
function FancyInput(options) {
this.options = options || {};
}
FancyInput.noConflict = function noConflict() {
global.FancyInput = previousFancyInput;
return FancyInput;
};
global.FancyInput = FancyInput;
}(this);
```
**[⬆ 回到頂端](#table-of-contents)**
## jQuery
- jQuery 的物件請使用 `$` 當前綴。
```javascript
// bad
var sidebar = $('.sidebar');
// good
var $sidebar = $('.sidebar');
```
- 快取 jQuery 的查詢。
```javascript
// bad
function setSidebar() {
$('.sidebar').hide();
// ...stuff...
$('.sidebar').css({
'background-color': 'pink'
});
}
// good
function setSidebar() {
var $sidebar = $('.sidebar');
$sidebar.hide();
// ...stuff...
$sidebar.css({
'background-color': 'pink'
});
}
```
- DOM 的查詢請使用層遞的 `$('.sidebar ul')` 或 父元素 > 子元素 `$('.sidebar > ul')` 。[jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16)
- 對作用域內的 jQuery 物件使用 `find` 做查詢。
```javascript
// bad
$('ul', '.sidebar').hide();
// bad
$('.sidebar').find('ul').hide();
// good
$('.sidebar ul').hide();
// good
$('.sidebar > ul').hide();
// good
$sidebar.find('ul').hide();
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="ecmascript-5-compatibility"></a>
## ECMAScript 5 相容性
- 參考 [Kangax](https://twitter.com/kangax/) 的 ES5 [相容性列表](http://kangax.github.com/es5-compat-table/).
**[⬆ 回到頂端](#table-of-contents)**
<a name="testing"></a>
## 測試
- **如題。**
```javascript
function() {
return true;
}
```
**[⬆ 回到頂端](#table-of-contents)**
<a name="performance"></a>
## 效能
- [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/)
- [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2)
- [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost)
- [Bang Function](http://jsperf.com/bang-function)
- [jQuery Find vs Context, Selector](http://jsperf.com/jquery-find-vs-context-sel/13)
- [innerHTML vs textContent for script text](http://jsperf.com/innerhtml-vs-textcontent-for-script-text)
- [Long String Concatenation](http://jsperf.com/ya-string-concat)
- Loading...
**[⬆ 回到頂端](#table-of-contents)**
<a name="resources"></a>
## 資源
**請讀這個**
- [Annotated ECMAScript 5.1](http://es5.github.com/)
**工具**
- Code Style Linters
+ [JSHint](http://www.jshint.com/) - [Airbnb Style .jshintrc](https://github.com/airbnb/javascript/blob/master/linters/.jshintrc)
+ [JSCS](https://github.com/jscs-dev/node-jscs) - [Airbnb Style Preset](https://github.com/jscs-dev/node-jscs/blob/master/presets/airbnb.json)
**其他的風格指南**
- [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml)
- [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines)
- [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/)
**其他風格**
- [Naming this in nested functions](https://gist.github.com/4135065) - Christian Johansen
- [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52) - Ross Allen
- [Popular JavaScript Coding Conventions on Github](http://sideeffect.kr/popularconvention/#javascript) - JeongHoon Byun
- [Multiple var statements in JavaScript, not superfluous](http://benalman.com/news/2012/05/multiple-var-statements-javascript/) - Ben Alman
**瞭解更多**
- [Understanding JavaScript Closures](http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) - Angus Croll
- [Basic JavaScript for the impatient programmer](http://www.2ality.com/2013/06/basic-javascript.html) - Dr. Axel Rauschmayer
- [You Might Not Need jQuery](http://youmightnotneedjquery.com/) - Zack Bloom & Adam Schwartz
- [ES6 Features](https://github.com/lukehoban/es6features) - Luke Hoban
- [Frontend Guidelines](https://github.com/bendc/frontend-guidelines) - Benjamin De Cock
**書籍**
- [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) - Douglas Crockford
- [JavaScript Patterns](http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) - Stoyan Stefanov
- [Pro JavaScript Design Patterns](http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X) - Ross Harmes and Dustin Diaz
- [High Performance Web Sites: Essential Knowledge for Front-End Engineers](http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309) - Steve Souders
- [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680) - Nicholas C. Zakas
- [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X) - Alex MacCaw
- [Pro JavaScript Techniques](http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273) - John Resig
- [Smashing Node.js: JavaScript Everywhere](http://www.amazon.com/Smashing-Node-js-JavaScript-Everywhere-Magazine/dp/1119962595) - Guillermo Rauch
- [Secrets of the JavaScript Ninja](http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X) - John Resig and Bear Bibeault
- [Human JavaScript](http://humanjavascript.com/) - Henrik Joreteg
- [Superhero.js](http://superherojs.com/) - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
- [JSBooks](http://jsbooks.revolunet.com/) - Julien Bouquillon
- [Third Party JavaScript](http://manning.com/vinegar/) - Ben Vinegar and Anton Kovalyov
- [Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript](http://amzn.com/0321812182) - David Herman
- [Eloquent JavaScript](http://eloquentjavascript.net) - Marijn Haverbeke
- [You Don't Know JS](https://github.com/getify/You-Dont-Know-JS) - Kyle Simpson
**部落格**
- [DailyJS](http://dailyjs.com/)
- [JavaScript Weekly](http://javascriptweekly.com/)
- [JavaScript, JavaScript...](http://javascriptweblog.wordpress.com/)
- [Bocoup Weblog](http://weblog.bocoup.com/)
- [Adequately Good](http://www.adequatelygood.com/)
- [NCZOnline](http://www.nczonline.net/)
- [Perfection Kills](http://perfectionkills.com/)
- [Ben Alman](http://benalman.com/)
- [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/)
- [Dustin Diaz](http://dustindiaz.com/)
- [nettuts](http://net.tutsplus.com/?s=javascript)
**Podcasts**
- [JavaScript Jabber](http://devchat.tv/js-jabber/)
**[⬆ 回到頂端](#table-of-contents)**
<a name="in-the-wild"></a>
## 誰在使用
這是正在使用這份風格指南的組織列表。送一個 pull request 或提一個 issue 讓我們將你增加到列表上。
- **Aan Zee**: [AanZee/javascript](https://github.com/AanZee/javascript)
- **Adult Swim**: [adult-swim/javascript](https://github.com/adult-swim/javascript)
- **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript)
- **Apartmint**: [apartmint/javascript](https://github.com/apartmint/javascript)
- **Avalara**: [avalara/javascript](https://github.com/avalara/javascript)
- **Billabong**: [billabong/javascript](https://github.com/billabong/javascript)
- **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide)
- **DailyMotion**: [dailymotion/javascript](https://github.com/dailymotion/javascript)
- **Digitpaint** [digitpaint/javascript](https://github.com/digitpaint/javascript)
- **Evernote**: [evernote/javascript-style-guide](https://github.com/evernote/javascript-style-guide)
- **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript)
- **Flexberry**: [Flexberry/javascript-style-guide](https://github.com/Flexberry/javascript-style-guide)
- **Gawker Media**: [gawkermedia/javascript](https://github.com/gawkermedia/javascript)
- **General Electric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript)
- **GoodData**: [gooddata/gdc-js-style](https://github.com/gooddata/gdc-js-style)
- **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript)
- **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript)
- **InfoJobs**: [InfoJobs/JavaScript-Style-Guide](https://github.com/InfoJobs/JavaScript-Style-Guide)
- **Intent Media**: [intentmedia/javascript](https://github.com/intentmedia/javascript)
- **Jam3**: [Jam3/Javascript-Code-Conventions](https://github.com/Jam3/Javascript-Code-Conventions)
- **JSSolutions**: [JSSolutions/javascript](https://github.com/JSSolutions/javascript)
- **Kinetica Solutions**: [kinetica/javascript](https://github.com/kinetica/javascript)
- **Mighty Spring**: [mightyspring/javascript](https://github.com/mightyspring/javascript)
- **MinnPost**: [MinnPost/javascript](https://github.com/MinnPost/javascript)
- **ModCloth**: [modcloth/javascript](https://github.com/modcloth/javascript)
- **Money Advice Service**: [moneyadviceservice/javascript](https://github.com/moneyadviceservice/javascript)
- **Muber**: [muber/javascript](https://github.com/muber/javascript)
- **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript)
- **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript)
- **Nimbl3**: [nimbl3/javascript](https://github.com/nimbl3/javascript)
- **Nordic Venture Family**: [CodeDistillery/javascript](https://github.com/CodeDistillery/javascript)
- **Orion Health**: [orionhealth/javascript](https://github.com/orionhealth/javascript)
- **Peerby**: [Peerby/javascript](https://github.com/Peerby/javascript)
- **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide)
- **reddit**: [reddit/styleguide/javascript](https://github.com/reddit/styleguide/tree/master/javascript)
- **REI**: [reidev/js-style-guide](https://github.com/reidev/js-style-guide)
- **Ripple**: [ripple/javascript-style-guide](https://github.com/ripple/javascript-style-guide)
- **SeekingAlpha**: [seekingalpha/javascript-style-guide](https://github.com/seekingalpha/javascript-style-guide)
- **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript)
- **StudentSphere**: [studentsphere/javascript](https://github.com/studentsphere/javascript)
- **Super**: [SuperJobs/javascript](https://github.com/SuperJobs/javascript)
- **Target**: [target/javascript](https://github.com/target/javascript)
- **TheLadders**: [TheLadders/javascript](https://github.com/TheLadders/javascript)
- **T4R Technology**: [T4R-Technology/javascript](https://github.com/T4R-Technology/javascript)
- **VoxFeed**: [VoxFeed/javascript-style-guide](https://github.com/VoxFeed/javascript-style-guide)
- **Weggo**: [Weggo/javascript](https://github.com/Weggo/javascript)
- **Zillow**: [zillow/javascript](https://github.com/zillow/javascript)
- **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript)
<a name="translation"></a>
## 翻譯
這份風格指南也提供其他語言的版本:
- ![br](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Brazil.png) **Brazilian Portuguese**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide)
- ![bg](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bulgaria.png) **Bulgarian**: [borislavvv/javascript](https://github.com/borislavvv/javascript)
- ![ca](https://raw.githubusercontent.com/fpmweb/javascript-style-guide/master/img/catala.png) **Catalan**: [fpmweb/javascript-style-guide](https://github.com/fpmweb/javascript-style-guide)
- ![tw](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Taiwan.png) **Chinese(Traditional)**: [jigsawye/javascript](https://github.com/jigsawye/javascript)
- ![cn](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/China.png) **Chinese(Simplified)**: [sivan/javascript-style-guide](https://github.com/sivan/javascript-style-guide)
- ![fr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/France.png) **French**: [nmussy/javascript-style-guide](https://github.com/nmussy/javascript-style-guide)
- ![de](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Germany.png) **German**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide)
- ![it](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Italy.png) **Italian**: [sinkswim/javascript-style-guide](https://github.com/sinkswim/javascript-style-guide)
- ![jp](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Japan.png) **Japanese**: [mitsuruog/javacript-style-guide](https://github.com/mitsuruog/javacript-style-guide)
- ![kr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/South-Korea.png) **Korean**: [tipjs/javascript-style-guide](https://github.com/tipjs/javascript-style-guide)
- ![pl](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Poland.png) **Polish**: [mjurczyk/javascript](https://github.com/mjurczyk/javascript)
- ![ru](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Russia.png) **Russian**: [uprock/javascript](https://github.com/uprock/javascript)
- ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [paolocarrasco/javascript-style-guide](https://github.com/paolocarrasco/javascript-style-guide)
- ![th](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Thailand.png) **Thai**: [lvarayut/javascript-style-guide](https://github.com/lvarayut/javascript-style-guide)
<a name="the-javascript-style-guide-guide"></a>
## JavaScript 風格指南
- [參考](https://github.com/airbnb/javascript/wiki/The-JavaScript-Style-Guide-Guide)
<a name="chat-with-us-about-javascript"></a>
## 與我們討論 JavaScript
- 請到 [gitter](https://gitter.im/airbnb/javascript) 尋找我們.
<a name="contributors"></a>
## 貢獻者
- [查看貢獻者](https://github.com/airbnb/javascript/graphs/contributors)
<a name="license"></a>
## 授權許可
(The MIT License)
Copyright (c) 2014 Airbnb
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**[⬆ 回到頂端](#table-of-contents)**
# };