標籤:strong asc 函數運算式 irb exp array col 3.1 提升
1 引用
1.1 對所有的引用使用 const ,不要使用 var。
(這能確保你無法對引用重新賦值,也不會導致出現 bug 或難以理解)
// bad var a = 1; var b = 2;// good const a = 1; const b = 2;
1.2 如果一定需要可變動的引用,使用 let 代替 var。
(因為 let 是塊級範圍,而 var 是函數範圍。)
// bad var count = 1; if (true) { count += 1; }// good, use the let. let count = 1; if (true) { count += 1; }2 對象2.1 使用字面值建立對象。
// badconst item = new Object();// goodconst item = {};2.2 使用對象方法的簡寫。
// badconst atom = { value: 1, addValue: function (value) { return atom.value + value; },};// goodconst atom = { value: 1, addValue(value) { return atom.value + value; },};2.3 使用對象屬性值的簡寫。
const lukeSkywalker = ‘Luke Skywalker‘;// bad const obj = { lukeSkywalker: lukeSkywalker, };// good const obj = { lukeSkywalker, };2.4 不要直接調用 Object.prototype 的方法,如:hasOwnProperty, propertyIsEnumerable, 和 isPrototypeOf
// badconsole.log(object.hasOwnProperty(key));// goodconsole.log(Object.prototype.hasOwnProperty.call(object, key));// bestconst has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope./* or */const has = require(‘has‘);…console.log(has.call(object, key));
2.5 淺拷貝對象的時候最好是使用 … 操作符而不是 Object.assign
// very badconst original = { a: 1, b: 2 };const copy = Object.assign(original, { c: 3 }); // this mutates `original`delete copy.a; // so does this
// badconst original = { a: 1, b: 2 };const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }// goodconst original = { a: 1, b: 2 };const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
3 數組3.1 使用字面值建立數組。eslint: no-array-constructor
// badconst items = new Array();// goodconst items = [];
3.2 使用拓展運算子 … 複製數組。
// badconst items = new Array();// goodconst items = [];// badconst len = items.length;const itemsCopy = [];let i;for(i = 0;i <len;i++){ itemsCopy[i] = items[i];}// goodconst itemsCopy = [...items];3.3 使用 Array#from 把一個類數組對象轉換成數組
const foo = document.querySelectorAll(‘.foo‘);const nodes = Array.from(foo);
4 函數4.1 使用函式宣告代替函數運算式
為什嗎?因為函式宣告是可命名的,所以他們在調用棧中更容易被識別。此外,函式宣告會把整個函數提升(hoisted),而函數運算式只會把函數的引用變數名提升。這條規則使得箭頭函數可以取代函數運算式。
// bad const foo = function () { }; // good function foo() { }4.2 函數運算式:
// 立即調用的函數運算式 (IIFE)(() => { console.log(‘Welcome to the Internet. Please follow me.‘);})();4.3 永遠不要在一個非函數代碼塊(if、while 等)中聲明一個函數,把那個函數賦給一個變數。瀏覽器允許你這麼做,但它們的解析表現不一致
// badif (currentUser) { function test() { console.log(‘Nope.‘); }}// goodlet test;if (currentUser) { test = () => { console.log(‘Yup.‘); };}4.4 不要使用 arguments。可以選擇 rest 文法 … 替代
為什嗎?使用 … 能明確你要傳入的參數。另外 rest 參數是一個真正的數組,而 arguments 是一個類數組。
// bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(‘‘); } // good function concatenateAll(...args) { return args.join(‘‘); }
5 箭頭函數5.1 當你必須使用函數運算式(或傳遞一個匿名函數)時,使用箭頭函數符號。
為什麼?因為箭頭函數創造了新的一個 this 執行環境(譯註:參考 Arrow functions - JavaScript | MDN 和 ES6 arrow functions, syntax and lexical scoping),通常情況下都能滿足你的需求,而且這樣的寫法更為簡潔。
為什麼不?如果你有一個相當複雜的函數,你或許可以把邏輯部分轉移到一個函式宣告上。
// bad [1, 2, 3].map(function (x) { return x * x; }); // good [1, 2, 3].map((x) => { return x * x; });
5.2 如果一個函數適合用一行寫出並且只有一個參數,那就把花括弧、圓括弧和 return 都省略掉。如果不是,那就不要省略
為什嗎?文法糖。在鏈式調用中可讀性很高。
為什麼不?當你打算回傳一個對象的時候。
// good [1, 2, 3].map(x => x * x); // good [1, 2, 3].reduce((total, n) => { return total + n; }, 0);6 構造器6.1 總是使用 class。避免直接操作 prototype
為什麼? 因為 class 文法更為簡潔更易讀。
// 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; } }
6.2 使用 extends 繼承。
為什嗎?因為 extends 是一個內建的原型繼承方法並且不會破壞 instanceof。
6.3 方法可以返回 this 來協助鏈式調用。7 模組7.1 總是使用模組 (import/export)7.2 不要使用萬用字元 import
// bad import * as AirbnbStyleGuide from ‘./AirbnbStyleGuide‘;// good import AirbnbStyleGuide from ‘./AirbnbStyleGuide‘;
7.3 不要從 import 中直接 export
// bad // filename es6.js export { es6 as default } from ‘./airbnbStyleGuide‘;// good // filename es6.js import { es6 } from ‘./AirbnbStyleGuide‘; export default es6;
8 Iterators and Generators8.1 不要使用 iterators,使用高階函數例如 map() 和 reduce() 替代 for-of
為什嗎?這加強了我們不變的規則。處理純函數的回調值更易讀,這比它帶來的副作用更重要。
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;
8.2 現在還不要使用 generators?
為什嗎?因為它們現在還沒法很好地編譯到 ES5。 (目前Chrome 和 Node.js 的穩定版本都已支援 generators)
9 變數9.1 一直使用 const 來聲明變數
如果不這樣做就會產生全域變數。我們需要避免全域命名空間的汙染。
// badsuperPower = new SuperPower();// goodconst superPower = new SuperPower();
9.2 使用 const 聲明每一個變數
為什嗎?增加新變數將變的更加容易,而且你永遠不用再擔心調換錯 ; 跟 ,。
9.3 將所有的 const 和 let 分組
為什嗎?當你需要把已賦值變數賦值給未賦值變數時非常有用。
// bad let i, len, dragonball, items = getItems(), goSportsTeam = true; // bad let i; const items = getItems(); let dragonball; const goSportsTeam = true; let len; // good const goSportsTeam = true; const items = getItems(); let dragonball; let i; let length;
9.4 在你需要的地方給變數賦值,但請把它們放在一個合理的位置
let 和 const 是塊級範圍而不是函數範圍。
10 提升10.1 var 聲明會被提升至該範圍的頂部,但它們賦值不會提升。
let 和 const 被賦予了一種稱為「暫時性死區(Temporal Dead Zones, TDZ)」的概念。這對於瞭解為什麼 type of 不再安全相當重要。
10.2 匿名函數運算式的變數名會被提升,但函數內容並不會。10.3 命名的函數運算式的變數名會被提升,但函數名和函數函數內容並不會。10.4 函式宣告的名稱和函數體都會被提升。11 比較子 & 等號11.1 優先使用 === 和 !== 而不是 == 和 !=.11.2 條件運算式例如 if 語句通過抽象方法 ToBoolean 強制計算它們的運算式並且總是遵守下面的規則:
o 對象 被計算為 true
o Undefined 被計算為 false
o Null 被計算為 false
o 布爾值 被計算為 布爾的值
o 數字 如果是 +0、-0、或 NaN 被計算為 false, 否則為 true
o 字串 如果是Null 字元串 ” 被計算為 false,否則為 true
12 注釋12.1 使用 /
* … / 作為多行注釋。包含描述、指定所有參數和傳回值的類型和值。
// bad// make() returns a new element// based on the passed in tag name//// @param {String} tag// @return {Element} elementfunction 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;}
12.2 使用 // 作為單行注釋。在注釋對象上面另起一行使用單行注釋。在注釋前插入空行。12.3 給注釋增加 FIXME 或 TODO 的首碼
協助其他開發人員快速瞭解這是一個需要複查的問題,或是給需要實現的功能提供一個解決方式。這將有別於常見的注釋,因為它們是可操作的。使用 FIXME – need to figure this out 或者 TODO – need to implement。
12.4 使用 // FIXME: 標註問題。
class Calculator { constructor() { // FIXME: shouldn‘t use a global here total = 0; }}
12.5 使用 // TODO: 標註問題的解決方式。
class Calculator { constructor() { // TODO: total should be configurable by an options param this.total = 0; }}13 空白13.1 使用 2 個空格作為縮排。13.2 在花括弧前要放一個空格。13.3 在控制語句(if、while 等)的小括弧前放一個空格。
在函數調用及聲明中,不在函數的參數列表前加空格。
13.4 在檔案末尾插入一個空行。13.5 在使用長方法鏈時進行縮排。使用放置在前面的點 . 強調這是方法調用而不是新語句。
Airbnb前端規範之javascript編碼規範