from airbnb translation https://github.com/lin-123/javascript
References
<a name="2.1"></a>
<a name="references--prefer-const"></a>
-
2.1 所有的賦值都用
const
,避免使用var
. eslint:prefer-const
,no-const-assign
Why? 因?yàn)檫@個確保你不會改變你的初始值坷随,重復(fù)引用會導(dǎo)致bug和代碼難以理解
// bad var a = 1; var b = 2; // good const a = 1; const b = 2;
<a name="2.2"></a>
<a name="references--disallow-var"></a>
-
2.2 如果你一定要對參數(shù)重新賦值房铭,那就用
let
,而不是var
. eslint:no-var
Why? 因?yàn)?code>let是塊級作用域温眉,而
var
是函數(shù)級作用域// bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; }
Objects
<a name="3.1"></a>
<a name="objects--no-new"></a>
-
3.1 使用字面值創(chuàng)建對象. eslint:
no-new-object
// bad const item = new Object(); // good const item = {};
<a name="3.2"></a>
<a name="es6-computed-properties"></a>
-
3.2 當(dāng)創(chuàng)建一個帶有動態(tài)屬性名的對象時够话,用計(jì)算后屬性名
Why? 這可以使你將定義的所有屬性放在對象的一個地方.
function getKey(k) { return `a key named ${k}`; } // bad const obj = { id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true; // good getKey('enabled')是動態(tài)屬性名 const obj = { id: 5, name: 'San Francisco', [getKey('enabled')]: true, };
<a name="3.4"></a>
<a name="es6-object-concise"></a>
-
3.4 用屬性值縮寫. eslint:
object-shorthand
Why? 這樣寫的更少且更可讀
const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, };
<a name="3.5"></a>
<a name="objects--grouped-shorthand"></a>
-
3.5 將你的所有縮寫放在對象聲明的開始.
Why? 這樣也是為了更方便的知道有哪些屬性用了縮寫.
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, };
<a name="3.6"></a>
<a name="objects--quoted-props"></a>
-
3.6 只對那些無效的標(biāo)示使用引號
''
. eslint:quote-props
Why? 通常我們認(rèn)為這種方式主觀上易讀。他優(yōu)化了代碼高亮双抽,并且頁更容易被許多JS引擎壓縮莺掠。
// bad const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // good const good = { foo: 3, bar: 4, 'data-blah': 5, };
<a name="3.8"></a>
<a name="objects--rest-spread"></a>
-
3.8 對象淺拷貝時露懒,更推薦使用擴(kuò)展運(yùn)算符[就是
...
運(yùn)算符],而不是Object.assign
砂心。獲取對象指定的幾個屬性時懈词,用對象的rest解構(gòu)運(yùn)算符[也是...
運(yùn)算符]更好。- 這一段不太好翻譯出來辩诞, 大家看下面的例子就懂了坎弯。.
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // this mutates `original` ?_?
delete copy.a; // so does this
// bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }
// good es6擴(kuò)展運(yùn)算符 ...
const original = { a: 1, b: 2 };
// 淺拷貝
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
// rest 賦值運(yùn)算符
const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
Arrays
<a name="4.1"></a>
<a name="arrays--literals"></a>
-
4.1 用字面量賦值。 eslint:
no-array-constructor
// bad const items = new Array(); // good const items = [];
<a name="4.2"></a>
<a name="arrays--push"></a>
-
4.2 用Array#push 代替直接向數(shù)組中添加一個值译暂。
const someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
<a name="4.3"></a>
<a name="es6-array-spreads"></a>
-
4.3 用擴(kuò)展運(yùn)算符做數(shù)組淺拷貝抠忘,類似上面的對象淺拷貝
// bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i += 1) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items];
<a name="4.4"></a>
<a name="arrays--from-iterable"></a>
-
4.4 用
...
運(yùn)算符而不是Array.from
來將一個可迭代的對象轉(zhuǎn)換成數(shù)組。const foo = document.querySelectorAll('.foo'); // good const nodes = Array.from(foo); // best const nodes = [...foo];
<a name="4.5"></a>
<a name="arrays--from-array-like"></a>
-
4.5 用
Array.from
去將一個類數(shù)組對象轉(zhuǎn)成一個數(shù)組外永。const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; // bad const arr = Array.prototype.slice.call(arrLike); // good const arr = Array.from(arrLike);
<a name="4.6"></a>
<a name="arrays--mapping"></a>
-
4.6 用
Array.from
而不是...
運(yùn)算符去做map遍歷崎脉。 因?yàn)檫@樣可以避免創(chuàng)建一個臨時數(shù)組。// bad const baz = [...foo].map(bar); // good const baz = Array.from(foo, bar);
Destructuring
<a name="5.1"></a>
<a name="destructuring--object"></a>
-
5.1 用對象的解構(gòu)賦值來獲取和使用對象某個或多個屬性值伯顶。 eslint:
prefer-destructuring
Why? 解構(gòu)保存了這些屬性的臨時值/引用
// 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}`; } // best function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; }
<a name="5.2"></a>
<a name="destructuring--array"></a>
-
5.2 用數(shù)組解構(gòu).
const arr = [1, 2, 3, 4]; // bad const first = arr[0]; const second = arr[1]; // good const [first, second] = arr;
<a name="5.3"></a>
<a name="destructuring--object-over-array"></a>
-
5.3 多個返回值用對象的解構(gòu)囚灼,而不是數(shù)組解構(gòu)。
Why? 你可以在后期添加新的屬性或者變換變量的順序而不會打破原有的調(diào)用
// bad function processInput(input) { // 然后就是見證奇跡的時刻 return [left, right, top, bottom]; } // 調(diào)用者需要想一想返回值的順序 const [left, __, top] = processInput(input); // good function processInput(input) { // oops砾淌, 奇跡又發(fā)生了 return { left, right, top, bottom }; } // 調(diào)用者只需要選擇他想用的值就好了 const { left, top } = processInput(input);
Strings
<a name="6.1"></a>
<a name="strings--quotes"></a>
-
6.1 對string用單引號
''
啦撮。 eslint:quotes
// bad const name = "Capt. Janeway"; // bad - 樣例應(yīng)該包含插入文字或換行 const name = `Capt. Janeway`; // good const name = 'Capt. Janeway';
<a name="6.2"></a>
<a name="strings--line-length"></a>
-
6.2 超過100個字符的字符串不應(yīng)該用string串聯(lián)成多行。
Why? 被折斷的字符串工作起來是糟糕的而且使得代碼更不易被搜索汪厨。
// 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.';
<a name="6.3"></a>
<a name="es6-template-literals"></a>
-
6.3 用字符串模板而不是字符串拼接來組織可編程字符串赃春。 eslint:
prefer-template
template-curly-spacing
Why? 模板字符串更具可讀性、語法簡潔劫乱、字符串插入?yún)?shù)织中。
// 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}?`; }
<a name="6.4"></a>
<a name="strings--eval"></a>
<a name="6.5"></a>
<a name="strings--escaping"></a>
-
6.5 不要使用不必要的轉(zhuǎn)義字符狭吼。eslint:
no-useless-escape
Why? 反斜線可讀性差,所以他們只在必須使用時才出現(xiàn)哦
// bad const foo = '\'this\' \i\s \"quoted\"'; // good const foo = '\'this\' is "quoted"'; //best const foo = `my name is '${name}'`;
Functions
<a name="7.5"></a>
<a name="functions--arguments-shadow"></a>
-
7.5 不要用
arguments
命名參數(shù)殖妇。他的優(yōu)先級高于每個函數(shù)作用域自帶的arguments
對象刁笙, 這會導(dǎo)致函數(shù)自帶的arguments
值被覆蓋// bad function foo(name, options, arguments) { // ... } // good function foo(name, options, args) { // ... }
<a name="7.6"></a>
<a name="es6-rest"></a>
-
7.6 不要使用
arguments
,用rest語法...
代替谦趣。 eslint:prefer-rest-params
Why?
...
明確你想用那個參數(shù)疲吸。而且rest參數(shù)是真數(shù)組,而不是類似數(shù)組的arguments
// bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function concatenateAll(...args) { return args.join(''); }
<a name="7.7"></a>
<a name="es6-default-parameters"></a>
-
7.7 用默認(rèn)參數(shù)語法而不是在函數(shù)里對參數(shù)重新賦值前鹅。
// really bad function handleThings(opts) { // 不摘悴, 我們不該改arguments // 第二: 如果 opts 的值為 false, 它會被賦值為 {} // 雖然你想這么寫, 但是這個會帶來一些細(xì)微的bug opts = opts || {}; // ... } // still bad function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // good function handleThings(opts = {}) { // ... }
<a name="7.9"></a>
<a name="functions--defaults-last"></a>
-
7.9 把默認(rèn)參數(shù)賦值放在最后
// bad function handleThings(opts = {}, name) { // ... } // good function handleThings(name, opts = {}) { // ... }
<a name="7.10"></a>
<a name="functions--constructor"></a>
-
7.10 不要用函數(shù)構(gòu)造器創(chuàng)建函數(shù)舰绘。 eslint:
no-new-func
Why? 以這種方式創(chuàng)建函數(shù)將類似于字符串 eval()蹂喻,這會打開漏洞葱椭。
// bad var add = new Function('a', 'b', 'return a + b'); // still bad var subtract = Function('a', 'b', 'return a - b');
<a name="7.12"></a>
<a name="functions--mutate-params"></a>
-
7.12 不要改參數(shù). eslint:
no-param-reassign
Why? 操作參數(shù)對象對原始調(diào)用者會導(dǎo)致意想不到的副作用。 就是不要改參數(shù)的數(shù)據(jù)結(jié)構(gòu)口四,保留參數(shù)原始值和數(shù)據(jù)結(jié)構(gòu)孵运。
// bad function f1(obj) { obj.key = 1; }; // good function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; };
<a name="7.13"></a>
<a name="functions--reassign-params"></a>
-
7.13 不要對參數(shù)重新賦值。 eslint:
no-param-reassign
Why? 參數(shù)重新賦值會導(dǎo)致意外行為窃祝,尤其是對
arguments
掐松。這也會導(dǎo)致優(yōu)化問題,特別是在V8里// bad function f1(a) { a = 1; // ... } function f2(a) { if (!a) { a = 1; } // ... } // good function f3(a) { const b = a || 1; // ... } function f4(a = 1) { // ... }
<a name="7.15"></a>
<a name="functions--signature-invocation-indentation"></a>
-
7.15 調(diào)用或者書寫一個包含多個參數(shù)的函數(shù)應(yīng)該想這個指南里的其他多行代碼寫法一樣: 每行值包含一個參數(shù)粪小,每行逗號結(jié)尾。
// bad function foo(bar, baz, quux) { // ... } // good 縮進(jìn)不要太過分 function foo( bar, baz, quux, ) { // ... } // bad console.log(foo, bar, baz); // good console.log( foo, bar, baz, );
Modules
<a name="10.2"></a>
<a name="modules--no-wildcard"></a>
-
10.2 不要用import通配符抡句, 就是
*
這種方式Why? 這確保你有單個默認(rèn)的導(dǎo)出
// bad import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // good import AirbnbStyleGuide from './AirbnbStyleGuide';
<a name="10.3"></a>
<a name="modules--no-export-from-import"></a>
-
10.3 不要直接從import中直接export
Why? 雖然一行是簡潔的探膊,有一個明確的方式進(jìn)口和一個明確的出口方式來保證一致性。
// bad // filename es6.js export { es6 as default } from './AirbnbStyleGuide'; // good // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6;
<a name="10.4"></a>
<a name="modules--no-duplicate-imports"></a>
-
10.4 一個路徑只 import 一次待榔。
eslint:no-duplicate-imports
Why? 從同一個路徑下import多行會使代碼難以維護(hù)
// bad import foo from 'foo'; // … some other imports … // import { named1, named2 } from 'foo'; // good import foo, { named1, named2 } from 'foo'; // good import foo, { named1, named2, } from 'foo';
<a name="10.5"></a>
<a name="modules--no-mutable-exports"></a>
-
10.5 不要導(dǎo)出可變的東西
eslint:import/no-mutable-exports
Why? 變化通常都是需要避免逞壁,特別是當(dāng)你要輸出可變的綁定。雖然在某些場景下可能需要這種技術(shù)锐锣,但總的來說應(yīng)該導(dǎo)出常量腌闯。
// bad let foo = 3; export { foo } // good const foo = 3; export { foo }
<a name="10.6"></a>
<a name="modules--prefer-default-export"></a>
-
10.6 在一個單一導(dǎo)出模塊里,用
export default
更好雕憔。
eslint:import/prefer-default-export
Why? 鼓勵使用更多文件姿骏,每個文件只做一件事情并導(dǎo)出,這樣可讀性和可維護(hù)性更好斤彼。
// bad export function foo() {} // good export default function foo() {}
<a name="10.7"></a>
<a name="modules--imports-first"></a>
-
10.7
import
放在其他所有語句之前分瘦。
eslint:import/first
Why? 讓
import
放在最前面防止意外行為。// bad import foo from 'foo'; foo.init(); import bar from 'bar'; // good import foo from 'foo'; import bar from 'bar'; foo.init();
<a name="10.8"></a>
<a name="modules--multiline-imports-over-newlines"></a>
-
10.8 多行import應(yīng)該縮進(jìn)琉苇,就像多行數(shù)組和對象字面量
Why? 花括號與樣式指南中每個其他花括號塊遵循相同的縮進(jìn)規(guī)則嘲玫,逗號也是。
// bad import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path'; // good import { longNameA, longNameB, longNameC, longNameD, longNameE, } from 'path';
教學(xué)項(xiàng)目中不換行并扇,選前者
Variables
<a name="13.3"></a>
<a name="variables--const-let-group"></a>
-
13.3
const
放一起去团,let
放一起Why? 在你需要分配一個新的變量, 而這個變量依賴之前分配過的變量的時候穷蛹,這種做法是有幫助的
// 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;
<a name="13.5"></a>
<a name="variables--no-chain-assignment"></a>
-
13.5 不要使用鏈?zhǔn)阶兞糠峙洹?eslint:
no-multi-assign
Why? 鏈接變量分配創(chuàng)建隱式全局變量土陪。
// bad (function example() { // JavaScript 將這一段解釋為 // let a = ( b = ( c = 1 ) ); // let 只對變量 a 起作用; 變量 b 和 c 都變成了全局變量 let a = b = c = 1; }()); console.log(a); // undefined console.log(b); // 1 console.log(c); // 1 // good (function example() { let a = 1; let b = a; let c = a; }()); console.log(a); // undefined console.log(b); // undefined console.log(c); // undefined // `const` 也是如此
<a name="13.6"></a>
<a name="variables--unary-increment-decrement"></a>
-
13.6 不要使用一元自增自減運(yùn)算符(
++
,--
). eslintno-plusplus
Why? 根據(jù)eslint文檔俩莽,一元增量和減量語句受到自動分號插入的影響旺坠,并且可能會導(dǎo)致應(yīng)用程序中的值遞增或遞減的無聲錯誤。 使用
num + = 1
而不是num ++
或num ++
語句來表達(dá)你的值也是更有表現(xiàn)力的扮超。 禁止一元增量和減量語句還會阻止您無意地預(yù)增/預(yù)減值取刃,這也會導(dǎo)致程序出現(xiàn)意外行為蹋肮。// bad let 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 let 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;
<a name="13.7"></a>
<a name="variables--linebreak"></a>
-
13.7 在賦值的時候避免在
=
前/后換行。 如果你的賦值語句超出max-len
璧疗, 那就用小括號把這個值包起來再換行坯辩。 eslintoperator-linebreak
.Why? 在
=
附近換行容易混淆這個賦值語句。// bad const foo = superLongLongLongLongLongLongLongLongFunctionName(); // bad const foo = 'superLongLongLongLongLongLongLongLongString'; // good const foo = ( superLongLongLongLongLongLongLongLongFunctionName() ); // good const foo = 'superLongLongLongLongLongLongLongLongString';
<a name="13.8"></a>
<a name="variables--no-unused-vars"></a>
-
13.8 不允許有未使用的變量崩侠。 eslint:
no-unused-vars
Why? 一個聲明了但未使用的變量更像是由于重構(gòu)未完成產(chǎn)生的錯誤漆魔。這種在代碼中出現(xiàn)的變量會使閱讀者迷惑。
// bad var some_unused_var = 42; // 寫了沒用 var y = 10; y = 5; // 變量改了自己的值却音,也沒有用這個變量 var z = 0; z = z + 1; // 參數(shù)定義了但未使用 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)); // 'type' 即使沒有使用也可以可以被忽略改抡, 因?yàn)檫@個有一個 rest 取值的屬性。 // 這是從對象中抽取一個忽略特殊字段的對象的一種形式 var { type, ...coords } = data; // 'coords' 現(xiàn)在就是一個沒有 'type' 屬性的 'data' 對象
Comparison Operators & Equality
<a name="15.1"></a>
<a name="comparison--eqeqeq"></a>
<a name="15.6"></a>
<a name="comparison--nested-ternaries"></a>
-
15.6 三元表達(dá)式不應(yīng)該嵌套系瓢,通常是單行表達(dá)式阿纤。
eslint rules:
no-nested-ternary
.// bad const foo = maybe1 > maybe2 ? "bar" : value1 > value2 ? "baz" : null; // better const maybeNull = value1 > value2 ? 'baz' : null; const foo = maybe1 > maybe2 ? 'bar' : maybeNull; // best const maybeNull = value1 > value2 ? 'baz' : null; const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
<a name="15.7"></a>
<a name="comparison--unneeded-ternary"></a>
-
15.7 避免不需要的三元表達(dá)式
eslint rules:
no-unneeded-ternary
.// 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;
<a name="15.8"></a>
<a name="comparison--no-mixed-operators"></a>
-
15.8 用圓括號來混合這些操作符。 只有當(dāng)標(biāo)準(zhǔn)的算術(shù)運(yùn)算符(
+
,-
,*
, &/
)夷陋, 并且它們的優(yōu)先級顯而易見時欠拾,可以不用圓括號括起來。 eslint:no-mixed-operators
Why? 這提高了可讀性骗绕,并且明確了開發(fā)者的意圖
// bad const foo = a && b < 0 || c > 0 || d + 1 === 0; // bad const bar = a ** b - 5 % d; // bad // 別人會陷入(a || b) && c 的迷惑中 if (a || b && c) { return 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
<a name="16.2"></a>
<a name="blocks--cuddled-elses"></a>
-
16.2
if
表達(dá)式的else
和if
的關(guān)閉大括號在一行藐窄。 eslint:brace-style
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
<a name="16.3"></a>
<a name="blocks--no-else-return"></a>
-
16.3 如果
if
語句中總是需要用return
返回, 那后續(xù)的else
就不需要寫了酬土。if
塊中包含return
荆忍, 它后面的else if
塊中也包含了return
, 這個時候就可以把return
分到多個if
語句塊中诺凡。 eslint:no-else-return
// 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
<a name="17.1"></a>
<a name="control-statements"></a>
-
17.1 當(dāng)你的控制語句(
if
,while
等)太長或者超過最大長度限制的時候东揣, 把每一個(組)判斷條件放在單獨(dú)一行里。 邏輯操作符放在行首腹泌。Why? 把邏輯操作符放在行首是讓操作符的對齊方式和鏈?zhǔn)胶瘮?shù)保持一致嘶卧。這提高了可讀性,也讓復(fù)雜邏輯更容易看清楚凉袱。
// 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(); }
<a name="17.2"></a>
<a name="control-statements--value-selection"></a>
-
17.2 不要用選擇操作符代替控制語句芥吟。
// bad !isRunning && startRunning(); // good if (!isRunning) { startRunning(); }
不做強(qiáng)制要求
Whitespace
<a name="19.1"></a>
<a name="whitespace--spaces"></a>
-
// bad function foo() { ????const name; } // bad function bar() { ?const name; } // good function baz() { ??const name; }
<a name="19.2"></a>
<a name="whitespace--before-blocks"></a>
-
19.2 在大括號前空一格。 eslint:
space-before-blocks
// 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', });
<a name="19.3"></a>
<a name="whitespace--around-keywords"></a>
-
19.3 在控制語句(
if
,while
等)的圓括號前空一格专甩。在函數(shù)調(diào)用和定義時钟鸵,參數(shù)列表和函數(shù)名之間不空格。 eslint:keyword-spacing
// bad if(isJedi) { fight (); } // good if (isJedi) { fight(); } // bad function fight () { console.log ('Swooosh!'); } // good function fight() { console.log('Swooosh!'); }
<a name="19.4"></a>
<a name="whitespace--infix-ops"></a>
-
19.4 用空格來隔開運(yùn)算符涤躲。 eslint:
space-infix-ops
// bad const x=y+5; // good const x = y + 5;
<a name="19.5"></a>
<a name="whitespace--newline-at-end"></a>
-
19.5 文件結(jié)尾空一行. eslint:
eol-last
// bad import { es6 } from './AirbnbStyleGuide'; // ... export default es6;
// bad import { es6 } from './AirbnbStyleGuide'; // ... export default es6;? ?
// good import { es6 } from './AirbnbStyleGuide'; // ... export default es6;?
<a name="19.6"></a>
<a name="whitespace--chains"></a>
-
19.6 當(dāng)出現(xiàn)長的方法鏈(>2個)時用縮進(jìn)棺耍。用點(diǎn)開頭強(qiáng)調(diào)該行是一個方法調(diào)用,而不是一個新的語句种樱。eslint:
newline-per-chained-call
no-whitespace-before-property
// 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);
<a name="19.7"></a>
<a name="whitespace--after-blocks"></a>
-
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;
<a name="19.8"></a>
<a name="whitespace--padded-blocks"></a>
-
19.8 不要用空白行填充塊俊卤。 eslint:
padded-blocks
// bad function bar() { console.log(foo); } // also bad if (baz) { console.log(qux); } else { console.log(foo); } // good function bar() { console.log(foo); } // good if (baz) { console.log(qux); } else { console.log(foo); }
<a name="19.9"></a>
<a name="whitespace--in-parens"></a>
-
19.9 圓括號里不要加空格。 eslint:
space-in-parens
// bad function bar( foo ) { return foo; } // good function bar(foo) { return foo; } // bad if ( foo ) { console.log(foo); } // good if (foo) { console.log(foo); }
<a name="19.10"></a>
<a name="whitespace--in-brackets"></a>
-
19.10 方括號里不要加空格害幅∠校看示例。 eslint:
array-bracket-spacing
// bad const foo = [ 1, 2, 3 ]; console.log(foo[ 0 ]); // good以现, 逗號分隔符還是要空格的 const foo = [1, 2, 3]; console.log(foo[0]);
<a name="19.11"></a>
<a name="whitespace--in-braces"></a>
-
19.11 花括號里加空格狠怨。 eslint:
object-curly-spacing
// bad const foo = {clark: 'kent'}; // good const foo = { clark: 'kent' };
<a name="19.12"></a>
<a name="whitespace--max-len"></a>
19.12 避免一行代碼超過120個字符(包含空格)。
-
注意: 對于上面——strings--line-length邑遏,長字符串不受此規(guī)則限制佣赖,不應(yīng)分解。 eslint:
max-len
Why? 這樣確奔呛校可讀性和可維護(hù)性
// 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.'));
<a name="19.13"></a>
<a name="whitespace--block-spacing"></a>
-
19.13 作為語句的花括號內(nèi)也要加空格 ——
{
后和}
前都需要空格茵汰。 eslint:block-spacing
// bad function foo() {return true;} if (foo) { bar = 0;} // good function foo() { return true; } if (foo) { bar = 0; }
<a name="19.14"></a>
<a name="whitespace--comma-spacing"></a>
-
19.14
,
前不要空格,,
后需要空格孽鸡。 eslint:comma-spacing
// bad var foo = 1,bar = 2; var arr = [1 , 2]; // good var foo = 1, bar = 2; var arr = [1, 2];
<a name="19.15"></a>
<a name="whitespace--computed-property-spacing"></a>
-
19.15 計(jì)算屬性內(nèi)要空格。參考上述花括號和中括號的規(guī)則栏豺。 eslint:
computed-property-spacing
// bad obj[foo ] obj[ 'foo'] var x = {[ b ]: a} obj[foo[ bar ]] // good obj[foo] obj['foo'] var x = { [b]: a } obj[foo[bar]]
<a name="19.16"></a>
<a name="whitespace--func-call-spacing"></a>
-
19.16 調(diào)用函數(shù)時彬碱,函數(shù)名和小括號之間不要空格。 eslint:
func-call-spacing
// bad func (); func (); // good func();
<a name="19.17"></a>
<a name="whitespace--key-spacing"></a>
-
19.17 在對象的字面量屬性中奥洼,
key
value
之間要有空格巷疼。 eslint:key-spacing
// bad var obj = { "foo" : 42 }; var obj2 = { "foo":42 }; // good var obj = { "foo": 42 };
<a name="19.18"></a>
<a name="whitespace--no-trailing-spaces"></a>
-
19.18 行末不要空格。 eslint:
no-trailing-spaces
<a name="19.19"></a>
<a name="whitespace--no-multiple-empty-lines"></a>
-
19.19 避免出現(xiàn)多個空行灵奖。 在文件末尾只允許空一行嚼沿。 eslint:
no-multiple-empty-lines
// bad var x = 1; var y = 2; // good var x = 1; var y = 2;
Commas
<a name="20.1"></a>
<a name="commas--leading-trailing"></a>
-
20.1 不要前置逗號。 eslint:
comma-style
// 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', };
<a name="20.2"></a>
<a name="commas--dangling"></a>
-
20.2 額外結(jié)尾逗號: 要 eslint:
comma-dangle
Why? 這導(dǎo)致git diffs更清潔瓷患。 此外骡尽,像Babel這樣的轉(zhuǎn)換器會刪除轉(zhuǎn)換代碼中的額外的逗號,這意味著你不必?fù)?dān)心舊版瀏覽器中的結(jié)尾逗號問題擅编。
// bad - 沒有結(jié)尾逗號的 git diff const hero = { firstName: 'Florence', - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'] }; // good - 有結(jié)尾逗號的 git diff 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 (note that a comma must not appear after a "rest" element) function createHero( firstName, lastName, inventorOf, ...heroArgs ) { // does nothing } // bad createHero( firstName, lastName, inventorOf ); // good createHero( firstName, lastName, inventorOf, ); // good (note that a comma must not appear after a "rest" element) createHero( firstName, lastName, inventorOf, ...heroArgs )
Semicolons
<a name="21.1"></a>
-
Why? 當(dāng) JavaScript 遇到?jīng)]有分號結(jié)尾的一行攀细,它會執(zhí)行自動插入分號
Automatic Semicolon Insertion
這一規(guī)則來決定行末是否加分號。如果JavaScript在你的斷行里錯誤的插入了分號爱态,就會出現(xiàn)一些古怪的行為谭贪。當(dāng)新的功能加到JavaScript里后, 這些規(guī)則會變得更復(fù)雜難懂锦担。顯示的結(jié)束語句俭识,并通過配置代碼檢查去捕獲沒有帶分號的地方可以幫助你防止這種錯誤。// bad (function () { const name = 'Skywalker' return name })() // good (function () { const name = 'Skywalker'; return name; }()); // good, 行首加分號洞渔,避免文件被連接到一起時立即執(zhí)行函數(shù)被當(dāng)做變量來執(zhí)行套媚。 ;(() => { const name = 'Skywalker'; return name; }());
Type Casting & Coercion
<a name="22.1"></a>
<a name="coercion--explicit"></a>
- 22.1 在語句開始執(zhí)行強(qiáng)制類型轉(zhuǎn)換缚态。
<a name="22.2"></a>
<a name="coercion--strings"></a>
-
22.2 Strings: eslint:
no-new-wrappers
// => this.reviewScore = 9; // bad const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string" // bad const totalScore = this.reviewScore + ''; // invokes this.reviewScore.valueOf() // bad const totalScore = this.reviewScore.toString(); // 不保證返回string // good const totalScore = String(this.reviewScore);
<a name="22.3"></a>
<a name="coercion--numbers"></a>
-
22.3 Numbers: 用
Number
做類型轉(zhuǎn)換,parseInt
轉(zhuǎn)換string常需要帶上基數(shù)凑阶。 eslint:radix
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);
<a name="22.6"></a>
<a name="coercion--booleans"></a>
-
22.6 布爾:
const age = 0; // bad const hasAge = new Boolean(age); // good const hasAge = Boolean(age); // best const hasAge = !!age;
<a name="23.4"></a>
<a name="naming--leading-underscore"></a>
-
23.4 不要用前置或后置下劃線猿规。 eslint:
no-underscore-dangle
Why? JavaScript 沒有私有屬性或私有方法的概念。盡管前置下劃線通常的概念上意味著“private”宙橱,事實(shí)上姨俩,這些屬性是完全公有的,因此這部分也是你的API的內(nèi)容师郑。這一概念可能會導(dǎo)致開發(fā)者誤以為更改這個不會導(dǎo)致崩潰或者不需要測試环葵。 如果你想要什么東西變成“private”,那就不要讓它在這里出現(xiàn)宝冕。
// bad this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; this._firstName = 'Panda'; // good this.firstName = 'Panda';
<a name="23.5"></a>
<a name="naming--self-this"></a>
-
23.5 不要保存引用
this
张遭, 用箭頭函數(shù)或函數(shù)綁定——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); }; }
<a name="23.6"></a>
<a name="naming--filename-matches-export"></a>
-
23.6 export default導(dǎo)出模塊A,則這個文件名也叫A.*地梨, import 時候的參數(shù)也叫A菊卷。 大小寫完全一致。
// file 1 contents class CheckBox { // ... } 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'; // PascalCase import/export, camelCase filename import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export // bad import CheckBox from './check_box'; // PascalCase import/export, snake_case filename import forty_two from './forty_two'; // snake_case import/filename, camelCase export import inside_directory from './inside_directory'; // snake_case import, camelCase export import index from './inside_directory/index'; // requiring the index file explicitly import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly // good import CheckBox from './CheckBox'; // PascalCase export/import/filename import fortyTwo from './fortyTwo'; // camelCase export/import/filename import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index" // ^ supports both insideDirectory.js and insideDirectory/index.js