用更合理的方式寫 JavaScriptjavascript
原文
翻譯自 Airbnb JavaScript Style Guide 。css
1.1 基本類型: 直接存取基本類型。html
字符串
數值
布爾類型
null
undefined
const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
1.2 複製類型: 經過引用的方式存取複雜類型。java
對象
數組
函數
const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
⬆ 返回目錄node
const
;避免使用 var
。爲何?這能確保你沒法對引用從新賦值,也不會致使出現 bug 或難以理解。jquery
```javascript // bad var a = 1; var b = 2; // good const a = 1; const b = 2; ```
let
代替 var
。爲何?由於
let
是塊級做用域,而var
是函數做用域。git
```javascript // bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; } ```
2.3 注意 let
和 const
都是塊級做用域。es6
// const 和 let 只存在於它們被定義的區塊內。 { let a = 1; const b = 1; } console.log(a); // ReferenceError console.log(b); // ReferenceError
⬆ 返回目錄github
3.1 使用字面值建立對象。web
// bad const item = new Object(); // good const item = {};
3.2 若是你的代碼在瀏覽器環境下執行,別使用 保留字 做爲鍵值。這樣的話在 IE8 不會運行。 更多信息。 但在 ES6 模塊和服務器端中使用沒有問題。
// bad const superman = { default: { clark: 'kent' }, private: true, }; // good const superman = { defaults: { clark: 'kent' }, hidden: true, };
3.3 使用同義詞替換須要使用的保留字。
// bad const superman = { class: 'alien', }; // bad const superman = { klass: 'alien', }; // good const superman = { type: 'alien', };
爲何?由於這樣可讓你在一個地方定義全部的對象屬性。
```javascript 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.5 使用對象方法的簡寫。
// bad const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // good const atom = { value: 1, addValue(value) { return atom.value + value; }, };
爲何?由於這樣更短更有描述性。
```javascript const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, }; ```
爲何?由於這樣能清楚地看出哪些屬性使用了簡寫。
```javascript const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { episodeOne: 1, twoJedisWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker, }; // good const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJedisWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4, }; ```
4.1 使用字面值建立數組。
// bad const items = new Array(); // good const items = [];
4.2 向數組添加元素時使用 Arrary#push 替代直接賦值。
const someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
4.3 使用拓展運算符 ...
複製數組。
// bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items];
4.4 使用 Array#from 把一個類數組對象轉換成數組。
const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo);
爲何?由於解構能減小臨時引用屬性。
```javascript // bad function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } // good function getFullName(obj) { const { firstName, lastName } = obj; return `${firstName} ${lastName}`; } // best 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) { // then a miracle occurs return [left, right, top, bottom]; } // 調用時須要考慮回調數據的順序。 const [left, __, top] = processInput(input); // good function processInput(input) { // then a miracle occurs return { left, right, top, bottom }; } // 調用時只選擇須要的數據 const { left, right } = processInput(input);
6.1 字符串使用單引號 ''
。
// bad const name = "Capt. Janeway"; // good const name = 'Capt. Janeway';
6.3 注:過分使用字串鏈接符號可能會對性能形成影響。jsPerf 和 討論.
// 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.';
爲何?模板字符串更爲簡潔,更具可讀性。
```javascript // bad function sayHi(name) { return 'How are you, ' + name + '?'; } // bad function sayHi(name) { return ['How are you, ', name, '?'].join(); } // good function sayHi(name) { return `How are you, ${name}?`; } ```
爲何?由於函數聲明是可命名的,因此他們在調用棧中更容易被識別。此外,函數聲明會把整個函數提高(hoisted),而函數表達式只會把函數的引用變量名提高。這條規則使得箭頭函數能夠取代函數表達式。
```javascript // bad const foo = function () { }; // good function foo() { } ```
7.2 函數表達式:
// 當即調用的函數表達式 (IIFE) (() => { console.log('Welcome to the Internet. Please follow me.'); })();
if
、while
等)中聲明一個函數,把那個函數賦給一個變量。瀏覽器容許你這麼作,但它們的解析表現不一致。7.4 注意: ECMA-262 把 block
定義爲一組語句。函數聲明不是語句。閱讀 ECMA-262 關於這個問題的說明。
// bad if (currentUser) { function test() { console.log('Nope.'); } } // good let test; if (currentUser) { test = () => { console.log('Yup.'); }; }
7.5 永遠不要把參數命名爲 arguments
。這將取代原來函數做用域內的 arguments
對象。
// bad function nope(name, options, arguments) { // ...stuff... } // good function yup(name, options, args) { // ...stuff... }
arguments
。能夠選擇 rest 語法 ...
替代。爲何?使用
...
能明確你要傳入的參數。另外 rest 參數是一個真正的數組,而arguments
是一個類數組。
```javascript // bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function concatenateAll(...args) { return args.join(''); } ```
7.7 直接給函數的參數指定默認值,不要使用一個變化的函數參數。
// really bad function handleThings(opts) { // 不!咱們不該該改變函數參數。 // 更加糟糕: 若是參數 opts 是 false 的話,它就會被設定爲一個對象。 // 但這樣的寫法會形成一些 Bugs。 //(譯註:例如當 opts 被賦值爲空字符串,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
爲何?由於箭頭函數創造了新的一個
this
執行環境(譯註:參考 Arrow functions - JavaScript | MDN 和 ES6 arrow functions, syntax and lexical scoping),一般狀況下都能知足你的需求,並且這樣的寫法更爲簡潔。
爲何不?若是你有一個至關複雜的函數,你或許能夠把邏輯部分轉移到一個函數聲明上。
```javascript // bad [1, 2, 3].map(function (x) { return x * x; }); // good [1, 2, 3].map((x) => { return x * x; }); ```
return
都省略掉。若是不是,那就不要省略。爲何?語法糖。在鏈式調用中可讀性很高。
爲何不?當你打算回傳一個對象的時候。
```javascript // good [1, 2, 3].map(x => x * x); // good [1, 2, 3].reduce((total, n) => { return total + n; }, 0); ```
class
。避免直接操做 prototype
。爲何? 由於
class
語法更爲簡潔更易讀。
```javascript // 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; } } ```
extends
繼承。爲何?由於
extends
是一個內建的原型繼承方法而且不會破壞instanceof
。
```javascript // 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(); // => 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()
方法,但要確保它能正常運行而且不會引發反作用。
class Jedi { constructor(options = {}) { this.name = options.name || 'no name'; } getName() { return this.name; } toString() { return `Jedi - ${this.getName()}`; } }
import
/export
) 而不是其餘非標準模塊系統。你能夠編譯爲你喜歡的模塊系統。爲何?模塊就是將來,讓咱們開始邁向將來吧。
```javascript // 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; ```
爲何?這樣能確保你只有一個默認 export。
```javascript // bad import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // good import AirbnbStyleGuide from './AirbnbStyleGuide'; ```
爲何?雖然一行代碼簡潔明瞭,但讓 import 和 export 各司其職讓事情能保持一致。
```javascript // bad // filename es6.js export { es6 as default } from './airbnbStyleGuide'; // good // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6; ```
map()
和 reduce()
替代 for-of
。爲何?這增強了咱們不變的規則。處理純函數的回調值更易讀,這比它帶來的反作用更重要。
```javascript 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; ```
爲何?由於它們如今還無法很好地編譯到 ES5。
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');
13.1 一直使用 const
來聲明變量,若是不這樣作就會產生全局變量。咱們須要避免全局命名空間的污染。地球隊長已經警告過咱們了。(譯註:全局,global 亦有全球的意思。地球隊長的責任是保衛地球環境,因此他警告咱們不要形成「全球」污染。)
// bad superPower = new SuperPower(); // good const superPower = new SuperPower();
13.2 使用 var
聲明每個變量。
爲何?增長新變量將變的更加容易,並且你永遠不用再擔憂調換錯
;
跟,
。
// 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
分組
爲何?當你須要把已賦值變量賦值給未賦值變量時很是有用。
```javascript // 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; ```
爲何?
let
和const
是塊級做用域而不是函數做用域。
```javascript // good function() { test(); console.log('doing stuff..'); //..other stuff.. const name = getName(); if (name === 'test') { return false; } return name; } // bad - unnecessary function call function(hasName) { const name = getName(); if (!hasName) { return false; } this.setFirstName(name); return true; } // good function(hasName) { if (!hasName) { return false; } const name = getName(); this.setFirstName(name); return true; } ```
14.1 var
聲明會被提高至該做用域的頂部,但它們賦值不會提高。let
和 const
被賦予了一種稱爲「暫時性死區(Temporal Dead Zones, TDZ)」的概念。這對於瞭解爲何 type of 再也不安全至關重要。
// 咱們知道這樣運行不了 // (假設 notDefined 不是全局變量) 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; } // 使用 const 和 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'); } }
想了解更多信息,參考 Ben Cherry 的 JavaScript Scoping & Hoisting。
===
和 !==
而不是 ==
和 !=
.15.2 條件表達式例如 if
語句經過抽象方法 ToBoolean
強制計算它們的表達式而且老是遵照下面的規則:
''
被計算爲 false,不然爲 trueif ([0]) { // true // An array is an object, objects evaluate to true }
15.3 使用簡寫。
// bad if (name !== '') { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... }
15.4 想了解更多信息,參考 Angus Croll 的 Truth Equality and JavaScript。
16.1 使用大括號包裹全部的多行代碼塊。
// bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function() { return false; } // good function() { return false; }
16.2 若是經過 if
和 else
使用多行代碼塊,把 else
放在 if
代碼塊關閉括號的同一行。
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
17.1 使用 /** ... */
做爲多行註釋。包含描述、指定全部參數和返回值的類型和值。
// bad // make() returns a new element // based on the passed in tag name // // @param {String} tag // @return {Element} element function make(tag) { // ...stuff... return element; } // good /** * make() returns a new element * based on the passed in tag name * * @param {String} tag * @return {Element} element */ function make(tag) { // ...stuff... return element; }
17.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; }
17.3 給註釋增長 FIXME
或 TODO
的前綴能夠幫助其餘開發者快速瞭解這是一個須要複查的問題,或是給須要實現的功能提供一個解決方式。這將有別於常見的註釋,由於它們是可操做的。使用 FIXME -- need to figure this out
或者 TODO -- need to implement
。
17.4 使用 // FIXME
: 標註問題。
class Calculator { constructor() { // FIXME: shouldn't use a global here total = 0; } }
17.5 使用 // TODO
: 標註問題的解決方式。
class Calculator { constructor() { // TODO: total should be configurable by an options param this.total = 0; } }
18.1 使用 2 個空格做爲縮進。
// bad function() { ∙∙∙∙const name; } // bad function() { ∙const name; } // good function() { ∙∙const name; }
18.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', });
18.3 在控制語句(if
、while
等)的小括號前放一個空格。在函數調用及聲明中,不在函數的參數列表前加空格。
// bad if(isJedi) { fight (); } // good if (isJedi) { fight(); } // bad function fight () { console.log ('Swooosh!'); } // good function fight() { console.log('Swooosh!'); }
18.4 使用空格把運算符隔開。
// bad const x=y+5; // good const x = y + 5;
18.5 在文件末尾插入一個空行。
// bad (function(global) { // ...stuff... })(this);
// bad (function(global) { // ...stuff... })(this);↵ ↵
// good (function(global) { // ...stuff... })(this);↵
18.5 在使用長方法鏈時進行縮進。使用前面的點 .
強調這是方法調用而不是新語句。
// 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').class('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);
18.6 在塊末和新語句前插入空行。
// 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;
19.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', };
19.2 增長結尾的逗號: 須要。
爲何? 這會讓 git diffs 更乾淨。另外,像 babel 這樣的轉譯器會移除結尾多餘的逗號,也就是說你沒必要擔憂老舊瀏覽器的尾逗號問題。
```javascript // bad - git diff without trailing comma const hero = { firstName: 'Florence', - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb graph', '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', ]; ```
20.1 使用分號
// bad (function() { const name = 'Skywalker' return name })() // good (() => { const name = 'Skywalker'; return name; })(); // good (防止函數在兩個 IIFE 合併時被當成一個參數) ;(() => { const name = 'Skywalker'; return name; })();
21.2 字符串:
// => this.reviewScore = 9; // bad const totalScore = this.reviewScore + ''; // good const totalScore = String(this.reviewScore);
21.3 對數字使用 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);
21.4 若是由於某些緣由 parseInt 成爲你所作的事的瓶頸而須要使用位操做解決性能問題時,留個註釋說清楚緣由和你的目的。
// good /** * 使用 parseInt 致使個人程序變慢, * 改爲使用位操做轉換數字快多了。 */ const val = inputValue >> 0;
21.5 注: 當心使用位操做運算符。數字會被當成 64 位值,可是位操做運算符老是返回 32 位的整數(參考)。位操做處理大於 32 位的整數值時還會致使意料以外的行爲。關於這個問題的討論。最大的 32 位整數是 2,147,483,647:
2147483647 >> 0 //=> 2147483647 2147483648 >> 0 //=> -2147483648 2147483649 >> 0 //=> -2147483647
21.6 布爾:
const age = 0; // bad const hasAge = new Boolean(age); // good const hasAge = Boolean(age); // good const hasAge = !!age;
22.1 避免單字母命名。命名應具有描述性。
// bad function q() { // ...stuff... } // good function query() { // ..stuff.. }
22.2 使用駝峯式命名對象、函數和實例。
// bad const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // good const thisIsMyObject = {}; function thisIsMyFunction() {}
22.3 使用帕斯卡式命名構造函數或類。
// 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', });
22.4 使用下劃線 _
開頭命名私有屬性。
// bad this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; // good this._firstName = 'Panda';
22.5 別保存 this
的引用。使用箭頭函數或 Function#bind。
// 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); }; }
22.6 若是你的文件只輸出一個類,那你的文件名必須和類名徹底保持一致。
// file contents class CheckBox { // ... } export default CheckBox; // in some other file // bad import CheckBox from './checkBox'; // bad import CheckBox from './check_box'; // good import CheckBox from './CheckBox';
22.7 當你導出默認的函數時使用駝峯式命名。你的文件名必須和函數名徹底保持一致。
function makeStyleGuide() { } export default makeStyleGuide;
22.8 當你導出單例、函數庫、空對象時使用帕斯卡式命名。
const AirbnbStyleGuide = { es6: { } }; export default AirbnbStyleGuide;
23.2 若是你須要存取函數時使用 getVal()
和 setVal('hello')
。
// bad dragon.age(); // good dragon.getAge(); // bad dragon.age(25); // good dragon.setAge(25);
23.3 若是屬性是布爾值,使用 isVal()
或 hasVal()
。
// bad if (!dragon.age()) { return false; } // good if (!dragon.hasAge()) { return false; }
23.4 建立 get()
和 set()
函數是能夠的,但要保持一致。
class Jedi { constructor(options = {}) { const lightsaber = options.lightsaber || 'blue'; this.set('lightsaber', lightsaber); } set(key, val) { this[key] = val; } get(key) { return this[key]; } }
24.1 當給時間附加數據時(不管是 DOM 事件仍是私有事件),傳入一個哈希而不是原始值。這樣可讓後面的貢獻者增長更多數據到事件數據而無需找出並更新事件的每個處理器。例如,很差的寫法:
// bad $(this).trigger('listingUpdated', listing.id); ... $(this).on('listingUpdated', function(e, listingId) { // do something with listingId });
更好的寫法:
// good $(this).trigger('listingUpdated', { listingId : listing.id }); ... $(this).on('listingUpdated', function(e, data) { // do something with data.listingId });
25.1 使用 $
做爲存儲 jQuery 對象的變量名前綴。
// bad const sidebar = $('.sidebar'); // good const $sidebar = $('.sidebar');
25.2 緩存 jQuery 查詢。
// bad function setSidebar() { $('.sidebar').hide(); // ...stuff... $('.sidebar').css({ 'background-color': 'pink' }); } // good function setSidebar() { const $sidebar = $('.sidebar'); $sidebar.hide(); // ...stuff... $sidebar.css({ 'background-color': 'pink' }); }
$('.sidebar ul')
或 父元素 > 子元素 $('.sidebar > ul')
。 jsPerf25.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();
28.1 Yup.
function() { return true; }
Learning ES6
Read This
Tools
Other Styleguides
Other Styles
Further Reading
Books
Blogs
Podcasts
This is a list of organizations that are using this style guide. Send us a pull request or open an issue and we'll add you to the list.
This style guide is also available in other languages:
(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.