用更合理的方式寫 JavaScript
<a name="table-of-contents"></a>
目錄
- 聲明變量
- 對象
- 數(shù)組
- 字符串
- 函數(shù)
- 箭頭函數(shù)
- 模塊
- 迭代器和生成器
- 屬性
- 變量
- 提升
- 比較運(yùn)算符和等號
- 代碼塊
- 注釋
- 空白
- 逗號
- 分號
- 類型轉(zhuǎn)換
- 命名規(guī)則
<a name="types"></a>
聲明變量
-
1.1 <a name='1.1'></a> 使用let和const代替var
- 不會變的聲明用const
//bad var $cat = $('.cat') //good const $cat = $('.cat')
- 會變動的聲明用let
//bad var count = 1 if (count<10) { count += 1 } //good let count = 1 if (count<10) { count += 1 }
-
1.2 <a name='1.2'></a> 將所有的
const
和let
分組為什么切省?當(dāng)你需要把已賦值變量賦值給未賦值變量時非常有用。
// 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;
-
1.3 <a name='1.3'></a> 在你需要的地方給變量賦值帕胆,但請把它們放在一個合理的位置朝捆。
為什么?
let
和const
是塊級作用域而不是函數(shù)作用域懒豹。// bad - unnecessary function call const checkName = function (hasName) { const name = getName(); if (hasName === 'test') { return false; } if (name === 'test') { this.setName(''); return false; } return name; }; // good const checkName = function (hasName) { if (hasName === 'test') { return false; } const name = getName(); if (name === 'test') { this.setName(''); return false; } return name; };
<a name="objects"></a>
對象 Objects
-
2.1 <a name='2.1'></a> 使用字面值創(chuàng)建對象芙盘。eslint:
no-new-object
// bad const item = new Object(); // good const item = {};
<a name="es6-computed-properties"></a>
-
2.2 <a name='2.2'></a> 創(chuàng)建有動態(tài)屬性名的對象時,使用可被計算的屬性名稱。
為什么?因為這樣可以讓你在一個地方定義所有的對象屬性庸蔼。
const getKey = function (k) { return `a key named ${k}`; }; // bad const obj = { id: 1, name: 'San Francisco', }; obj[getKey('enabled')] = true; // good const obj = { id: 1, name: 'San Francisco', [getKey('enabled')]: true, };
<a name="es6-object-shorthand"></a>
-
2.3 <a name='2.3'></a> 使用對象方法的簡寫杠巡。eslint:
object-shorthand
// bad const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // good const atom = { value: 1, addValue(value) { return atom.value + value; }, };
<a name="es6-object-concise"></a>
-
2.4 <a name='2.4'></a> 使用對象屬性值的簡寫。eslint:
object-shorthand
為什么?因為這樣更短更有描述性。
const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, };
-
2.5 <a name='2.5'></a> 在對象屬性聲明前把簡寫的屬性分組。
為什么囚衔?因為這樣能清楚地看出哪些屬性使用了簡寫。
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, };
-
2.6 <a name='2.6'></a> ==只==把對象中是無效標(biāo)識符的屬性用引號括起來雕沿。 eslint:
quote-props
為什么佳魔?通常認(rèn)為這樣寫更容易閱讀,更好的支持語法高亮晦炊,也更容易被許多 JS 引擎優(yōu)化鞠鲜。
// bad const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // good const good = { foo: 3, bar: 4, 'data-blah': 5, };
-
2.7 <a name='2.7'></a> 不要直接調(diào)用
Object.prototype
方法,比如hasOwnProperty
,propertyIsEnumerable
,和isPrototypeOf
断国。為什么贤姆?這些方法有可能被對象本身的方法所遮蔽 - 比如
{ hasOwnProperty: false }
- 或者, 這個對象是個 null object (Object.create(null)
)。// bad console.log(object1.hasOwnProperty(key)); // good console.log(Object.prototype.hasOwnProperty.call(object, key)); // best const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope. /* or */ import has from 'has'; // https://www.npmjs.com/package/has // ... console.log(has.call(object, key));
-
2.8 <a name='2.8'></a> 使用對象字面量創(chuàng)建對象時稳衬,大括號必須換行霞捡。使用對象解構(gòu)賦值時,如果對象屬性超過2個薄疚,必須換行碧信。eslint:
object-curly-newline
// bad const original = {a: 1, b: 2}; const {height, largeSize, smallSize} = item; // good const original = { a: 1, b: 2, }; const { height, largeSize, smallSize, } = item; const {height, largeSize} = item;
-
2.9 <a name='2.9'></a>
單行定義對象時赊琳,最后一個成員不以逗號結(jié)尾。多行定義的對象砰碴,最后一個成員以逗號結(jié)尾躏筏。// bad const foo = { k1: v1, k2: v2, }; const bar = { k1: v1, k2: v2 }; // good const foo = { k1: v1, k2: v2 }; const bar = { k1: v1, k2: v2, };
<a name="arrays"></a>
數(shù)組 Arrays
-
3.1 <a name='3.1'></a> 使用字面值創(chuàng)建數(shù)組。eslint:
no-array-constructor
// bad const items = new Array(); // good const items = [];
-
3.2 <a name='3.2'></a> 向數(shù)組添加元素時使用 Array#push 替代直接賦值呈枉。
const someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
<a name="es6-array-spreads"></a>
-
3.3 <a name='3.3'></a> 使用擴(kuò)展運(yùn)算符
...
復(fù)制數(shù)組趁尼。// bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items];
-
3.4 <a name='3.4'></a> 使用擴(kuò)展運(yùn)算符
...
代替 Array.from 把一個類數(shù)組對象轉(zhuǎn)換成數(shù)組。const foo = document.querySelectorAll('.foo'); // good const nodes = Array.from(foo); // best const nodes = [...foo];
-
3.5 <a name='3.5'></a> 使用 Array.from 代替擴(kuò)展運(yùn)算符
...
來映射迭代器猖辫,因為這樣可以避免創(chuàng)建一個中間數(shù)組酥泞。(array.from可以把類數(shù)組或者字符串轉(zhuǎn)化為數(shù)組)// bad const baz = [...foo].map(bar); // good const baz = Array.from(foo, bar);
-
3.6 <a name='3.6'></a> 在數(shù)組方法的回調(diào)中使用return語句。如果函數(shù)只有一行代碼啃憎,并且只返回了一個表達(dá)式芝囤,那么可以省略返回值。關(guān)聯(lián) 7.2. eslint:
array-callback-return
// good [1, 2, 3].map((x) => { const y = x + 1; return x * y; }); // good [1, 2, 3].map(x => x + 1); // bad - no returned value means `memo` becomes undefined after the first iteration [[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => { const flatten = memo.concat(item); memo[index] = flatten; }); // good [[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => { const flatten = memo.concat(item); memo[index] = flatten; return flatten; }); // bad inbox.filter((msg) => { const {subject, author} = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } else { return false; } }); // good inbox.filter((msg) => { const {subject, author} = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } return false; });
-
3.7 如果數(shù)組有多行辛萍,請在打開和關(guān)閉數(shù)組括號前使用換行符悯姊。eslint:
array-bracket-newline
// bad const arr = [ [0, 1], [2, 3], [4, 5], ]; const objectInArray = [{ id: 1, }, { id: 2, }]; const numberInArray = [ 1, 2, ]; // good const arr = [[0, 1], [2, 3], [4, 5]]; const objectInArray = [ { id: 1, }, { id: 2, }, ]; const numberInArray = [ 1, 2, ];
-
3.8 禁止使用稀疏數(shù)組。eslint:
no-sparse-arrays
// bad const color = ['red',, 'blue']; // good const color = ['red', 'blue'];
<a name="strings"></a>
字符串 Strings
-
4.1 <a name='4.1'></a> 字符串使用單引號
''
叹阔。eslint:quotes
// bad const name = "Capt. Janeway"; // bad - template literals should contain interpolation or newlines const name = `Capt. Janeway`; // good const name = 'Capt. Janeway';
4.2 <a name='4.2'></a> 字符串超過 ==80== 個字節(jié)應(yīng)該使用字符串連接號換行挠轴。
-
4.3 <a name='4.3'></a> 注:過度使用字串連接符號可能會對性能造成影響传睹。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.';
<a name="es6-template-literals"></a>
-
4.4 <a name='4.4'></a> 程序化生成字符串時睛藻,使用模板字符串代替字符串連接。eslint:
prefer-template
template-curly-spacing
為什么邢隧?模板字符串更為簡潔店印,更具可讀性。
// bad const sayHi = function (name) { return 'How are you, ' + name + '?'; }; // bad const sayHi = function (name) { return ['How are you, ', name, '?'].join(); }; // bad const sayHi = function (name) { return `How are you, ${ name }?`; }; // good const sayHi = function (name) { return `How are you, ${name}?`; };
<a name="strings--eval"></a>
<a name="strings--escaping"></a>
-
4.6 <a name='4.6'></a> 不要在字符串中使用不必要的轉(zhuǎn)義字符。 eslint:
no-useless-escape
為什么纫谅?反斜杠導(dǎo)致代碼不可讀炫贤,因此應(yīng)該在必要的時候使用。
// bad const foo = '\'this\' \i\s \"quoted\"'; // good const foo = '\'this\' is "quoted"'; const foo = `my name is '${name}'`;
<a name="functions"></a>
函數(shù) Functions
-
5.1 <a name='5.1'></a> 使用函數(shù)表達(dá)式代替函數(shù)聲明(頂級函數(shù)不受限制)付秕。eslint:
func-style
為什么兰珍?函數(shù)聲明會把整個函數(shù)提升(hoisted),這導(dǎo)致在函數(shù)定義之前就可以引用該函數(shù)询吴。這會影響代碼的可讀性和可維護(hù)性掠河。
// bad function foo() { // ... } // good const foo = function () { // ... };
-
5.2 <a name='5.2'></a> 用括號包裹立即執(zhí)行函數(shù)表達(dá)式亮元。 eslint:
wrap-iife
為什么?立即執(zhí)行函數(shù)表達(dá)式是個單獨(dú)的模塊唠摹,用括號將函數(shù)和表示函數(shù)執(zhí)行的括號包裹起來爆捞,會使代碼更清晰。
// 立即執(zhí)行函數(shù)表達(dá)式 (IIFE) (function () { console.log('Welcome to the Internet. Please follow me.'); }());
5.3 <a name='5.3'></a> 永遠(yuǎn)不要在一個非函數(shù)代碼塊(
if
跃闹、while
等)中聲明一個函數(shù)嵌削,應(yīng)該把函數(shù)賦給代碼塊外部的一個變量。瀏覽器允許你這么做望艺,但它們的解析表現(xiàn)不一致苛秕。eslint:no-loop-func
注意: ECMA-262 把block
定義為一組語句。函數(shù)聲明不是語句找默。閱讀 ECMA-262 關(guān)于這個問題的說明//bad if (foo) { function test () { ... } //good let test; if(foo) { test = () => { ... } }
-
5.4 <a name='6.4'></a> 永遠(yuǎn)不要把參數(shù)命名為
arguments
艇劫。這將取代原來函數(shù)作用域內(nèi)的arguments
對象。// bad const nope = function (name, options, arguments) { // ...stuff... }; // good const yup = function (name, options, args) { // ...stuff... };
<a name="es6-rest"></a>
-
5.5 <a name='5.5'></a> 不要使用
arguments
惩激〉晟罚可以選擇 rest 語法...
替代。eslint:prefer-rest-params
為什么风钻?使用
...
能明確你要傳入的參數(shù)顷蟀。另外 rest 參數(shù)是一個真正的數(shù)組,而arguments
是一個類數(shù)組骡技。// bad const concatenateAll = function () { const args = Array.prototype.slice.call(arguments); return args.join(''); }; // good const concatenateAll = function (...args) { return args.join(''); };
<a name="es6-default-parameters"></a>
-
5.6 <a name='5.6'></a> 直接給函數(shù)的參數(shù)指定默認(rèn)值鸣个,不要使用一個變化的函數(shù)參數(shù)。
// really bad const handleThings = function (opts) { // 不布朦!我們不應(yīng)該改變函數(shù)參數(shù)囤萤。 // 更加糟糕: 如果參數(shù) opts 是 false 的話,它就會被設(shè)定為一個對象是趴。 // 但這樣的寫法會造成一些 Bugs涛舍。 //(譯注:例如當(dāng) opts 被賦值為空字符串,opts 仍然會被下一行代碼設(shè)定為一個空對象唆途。) opts = opts || {}; // ... }; // still bad const handleThings = function (opts) { if (opts === void 0) { opts = {}; } // ... }; // good const handleThings = function (opts = {}) { // ... };
-
5.7 <a name='5.7'></a> 直接給函數(shù)參數(shù)賦值時需要避免副作用富雅。
為什么?因為這樣的寫法讓人感到很困惑肛搬。
var b = 1; // bad const count = function (a = b++) { console.log(a); }; count(); // 1 count(); // 2 count(3); // 3 count(); // 3
<a name="functions--constructor"></a><a name="5.8"></a>
-
5.8 不要使用構(gòu)造函數(shù)的方式創(chuàng)建一個新函數(shù)没佑。 eslint:
no-new-func
為什么?用構(gòu)造函數(shù)的方式創(chuàng)建函數(shù)類似于用 eval() 創(chuàng)建字符串滚婉,會有很多缺陷图筹。
// bad var add = new Function('a', 'b', 'return a + b'); // still bad var subtract = Function('a', 'b', 'return a - b');
(所以是不使用class語法的意思嗎)
<a name="functions--signature-spacing"></a><a name="5.9"></a>
-
6.9 function 關(guān)鍵詞的空格。 eslint:
space-before-function-paren
space-before-blocks
為什么?保持一致性远剩,這樣在添加和刪除函數(shù)時就不需要修改空格了扣溺。
// bad const fetch = function(){}; const get = function (){}; const hold = function() {}; // good const fetch = function () {};
<a name="functions--spread-vs-apply"></a><a name="5.10"></a>
-
5.10 優(yōu)先使用擴(kuò)展運(yùn)算符
...
來調(diào)用參數(shù)可變的函數(shù)。 eslint:prefer-spread
為什么瓜晤? 這樣寫代碼更干凈锥余,不必提供上下文。
// bad const x = [1, 2, 3, 4, 5]; console.log.apply(console, x); // good const x = [1, 2, 3, 4, 5]; console.log(...x); // bad new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5])); // good new Date(...[2016, 8, 5]);
<a name="functions--defaults-last"></a><a name="5.11"></a>
-
5.11 有默認(rèn)值的參數(shù)總是放在最后一個痢掠。
// bad const handleThings = function (opts = {}, name) { // ... }; // good const handleThings = function (name, opts = {}) { // ... }; ``` ```
<a name="functions--complexity"></a><a name="5.12"></a>
-
5.12 建議函數(shù)的圈復(fù)雜度(代碼的獨(dú)立現(xiàn)行路徑條數(shù))==在20以內(nèi)==驱犹。 eslint:
complexity
為什么? 這樣可以減少函數(shù)的復(fù)雜度足画,使函數(shù)容易看懂雄驹。
<a name="arrow-functions"></a>
箭頭函數(shù)
-
6.1 <a name='6.1'></a> 當(dāng)你必須使用函數(shù)表達(dá)式(或傳遞一個匿名函數(shù))時,使用箭頭函數(shù)符號淹辞。eslint:
prefer-arrow-callback
,arrow-spacing
為什么医舆?因為箭頭函數(shù)創(chuàng)造了新的一個
this
執(zhí)行環(huán)境(譯注:參考 Arrow functions - JavaScript | MDN 和 ES6 arrow functions, syntax and lexical scoping),通常情況下都能滿足你的需求象缀,而且這樣的寫法更為簡潔蔬将。為什么不?如果你有一個相當(dāng)復(fù)雜的函數(shù)央星,你或許可以把邏輯部分轉(zhuǎn)移到一個函數(shù)聲明上霞怀。
// bad [1, 2, 3].map(function (num) { const sum = num + 1; return num * sum; }); // good [1, 2, 3].map((num) => { const sum = num + 1; return num * sum; });
-
6.2 <a name='6.2'></a> 如果一個函數(shù)適合用一行寫出并且只有一個參數(shù),那就把花括號莉给、圓括號和
return
都省略掉毙石。如果不是,那就不要省略禁谦。eslint:arrow-parens
,arrow-body-style
為什么胁黑?語法糖废封。在鏈?zhǔn)秸{(diào)用中可讀性很高州泊。
// bad [1, 2, 3].map((number) => { const nextNumber = number + 1; `A string containing the ${nextNumber}.`; }); // good [1, 2, 3].map((number) => `A string containing the ${number}.`); // good [1, 2, 3].map((number) => { const nextNumber = number + 1; return `A string containing the ${nextNumber}.`; }); // good [1, 2, 3].map((number, index) => ({ [index]: number, })); // No implicit return with side effects const foo = function (callback) { const val = callback(); if (val === true) { // Do something if callback returns true } }; let bool = false; // bad foo(() => bool = true); // good foo(() => { bool = true; });
<a name="arrows--paren-wrap"></a><a name="6.3"></a>
-
6.3 如果一個表達(dá)式跨行了,必須用括號括起來增強(qiáng)可讀性漂洋。
為什么遥皂?這使得函數(shù)開始和結(jié)束的位置非常清晰。
// bad ['get', 'post', 'put'].map((httpMethod) => Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod, ) ); // good ['get', 'post', 'put'].map((httpMethod) => ( Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod, ) ));
<a name="arrows--one-arg-parens"></a><a name="6.4"></a>
-
6.4 入?yún)⒈仨氂美ㄌ柪ㄆ饋砉羝slint:
arrow-parens
為什么演训? 保持代碼清晰和一致性。
// bad [1, 2, 3].map(num => num * num); // good [1, 2, 3].map((num) => num * num); // bad [1, 2, 3].map(num => { const sum = num + 1; return num * sum; }); // good [1, 2, 3].map((num) => { const sum = num + 1; return num * sum; });
<a name="arrows--confusing"></a><a name="6.5"></a>
-
6.5 避免混用箭頭函數(shù)的語法 (
=>
) 和比較運(yùn)算符 (<=
,>=
)贝咙。 eslint:no-confusing-arrow
// bad const itemHeight = item => item.height > 1000 ? item.largeSize : item.smallSize; // bad const itemHeight = (item) => item.height > 1000 ? item.largeSize : item.smallSize; // good const itemHeight = (item) => (item.height > 1000 ? item.largeSize : item.smallSize); // good const itemHeight = (item) => { const { height, largeSize, smallSize, } = item; return height > 1000 ? largeSize : smallSize; };
<a name="modules"></a>
模塊 Modules
-
7.1 <a name='7.1'></a> 總是使用模組 (
import
/export
) 而不是其他非標(biāo)準(zhǔn)模塊系統(tǒng)样悟。你可以編譯為你喜歡的模塊系統(tǒng)。為什么?模塊化是未來趨勢窟她。
// 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;
-
7.2 <a name='7.2'></a> 不要使用通配符 import陈症。
為什么?這樣能確保你只有一個默認(rèn) export震糖。
// bad import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // good import AirbnbStyleGuide from './AirbnbStyleGuide';
-
7.3 <a name='7.3'></a>不要從 import 中直接 export录肯。
為什么?雖然一行代碼簡潔明了吊说,但讓 import 和 export 各司其職讓事情能保持一致论咏。
// bad // filename es6.js export {es6 as default} from './airbnbStyleGuide'; // good // filename es6.js import {es6} from './AirbnbStyleGuide'; export default es6;
<a name="modules--no-duplicate-imports"></a>
-
7.4 不要多次 import 同一個文件。eslint:
no-duplicate-imports
Why? 多個地方引入同一個文件會使代碼難以維護(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="iterators-and-generators"></a>
Iterators and Generators
-
8.1 <a name='8.1'></a> 不要使用 iterators厅贪。使用高階函數(shù)例如
map()
和reduce()
替代for-of
和for-in
。eslint:no-iterator
no-restricted-syntax
為什么雅宾?這加強(qiáng)了我們不變的規(guī)則卦溢。處理純函數(shù)的回調(diào)值更易讀,這比它帶來的副作用更重要秀又。
使用
map()
单寂、every()
、filter()
吐辙、find()
宣决、findIndex()
、reduce()
昏苏、some()
...來遍歷數(shù)組尊沸,使用Object.keys()
、Object.values()
贤惯、Object.entries()
生成數(shù)組以便遍歷對象洼专。const numbers = [1, 2, 3, 4]; // bad let sum = 0; for (let num of numbers) { sum += num; } sum === 10; // good let sum = 0; numbers.forEach((num) => { sum += num; }); sum === 10; // best (use the functional force) const sum = numbers.reduce((total, num) => total + num, 0); sum === 10;
-
8.2 <a name='8.2'></a> 現(xiàn)在還不要使用 generators。
為什么孵构?因為它們現(xiàn)在還沒法很好地編譯到 ES5屁商。
<a name="properties"></a>
屬性 Properties
-
9.1 <a name='9.1'></a> 使用
.
來訪問對象的屬性。eslint:dot-notation
const luke = { jedi: true, age: 12, }; // bad const isJedi = luke['jedi']; // good const isJedi = luke.jedi;
-
9.2 <a name='9.2'></a> 當(dāng)通過變量訪問屬性時使用中括號
[]
颈墅。const luke = { jedi: true, age: 12, }; const getProp = (prop) => { return luke[prop]; } const isJedi = getProp('jedi');
<a name="variables"></a>
變量 Variables
<a name="variables--no-chain-assignment"></a><a name="10.1"></a>
-
11.1 不要鏈?zhǔn)降慕o變量賦值蜡镶。eslint:
no-multi-assign
為什么?鏈?zhǔn)阶兞抠x值會創(chuàng)建隱式的全局變量恤筛。
// bad (function example() { // JavaScript interprets this as // let a = ( b = ( c = 1 ) ); // The let keyword only applies to variable a; variables b and c become // global variables. let cat = dog = bird = 1; }()); console.log(cat); // throws ReferenceError console.log(dog); // 1 console.log(bird); // 1 // good (function example() { let cat = 1; let dog = cat; let bird = cat; }()); console.log(cat); // throws ReferenceError console.log(dogb); // throws ReferenceError console.log(bird); // throws ReferenceError // the same applies for `const`
<a name="variables--unary-increment-decrement"></a><a name="10.2"></a>
-
10.2 避免使用累加和累減符號 (++, --)官还。 eslint
no-plusplus
為什么?根據(jù) eslint 文檔毒坛,累加和累減會受到自動插入分號的影響望伦,并可能導(dǎo)致一些意外情況發(fā)生林说。
// bad const 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 const 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="variables--no-magic-numbers"></a><a name="10.3"></a>
-
10.3 避免使用魔法數(shù)字(白名單如下)。 eslint
no-magic-numbers
為什么屯伞?魔法數(shù)字讓人難難以明白開發(fā)者的意圖是什么述么,破壞代碼的可讀性和可維護(hù)性。
// 以下為魔法數(shù)字白名單 let magicNumberIgnore = []; // baisc number magicNumberIgnore = magicNumberIgnore.concat([ -1, 0, 100, 1000, 10000 ]); // datetime number magicNumberIgnore = magicNumberIgnore.concat([ 12, 24, 60, 3600 ]); // httpcode number magicNumberIgnore = magicNumberIgnore.concat([ 200, 301, 302, 303, 304, 400, 401, 402, 403, 404, 500, 501, 502, 503, 504 ]); // bit number magicNumberIgnore = magicNumberIgnore.concat([ 1024 ]); // number 1-49 for (i = 1; i <= 49; i++) { if (magicNumberIgnore.indexOf(i) === -1) { magicNumberIgnore.push(i); } }
// bad let soldNum = 102; let initNum = 80; // good const APPLE = 102; const STOCK = 80; let soldNum = APPLE; let initNum = STOCK;
<a name="hoisting"></a>
Hoisting
-
11.1 <a name='11.1'></a>
var
聲明會被提升至該作用域的頂部愕掏,但它們賦值不會提升度秘。let
和const
被賦予了一種稱為「暫時性死區(qū)(Temporal Dead Zones, TDZ)」的概念。這對于了解為什么 typeof 不再安全相當(dāng)重要饵撑。// 我們知道這樣運(yùn)行不了 // (假設(shè) notDefined 不是全局變量) const example = function () { console.log(notDefined); // => throws a ReferenceError }; // 由于變量提升的原因剑梳, // 在引用變量后再聲明變量是可以運(yùn)行的。 // 注:變量的賦值 `true` 不會被提升滑潘。 const example = function () { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; }; // 編譯器會把函數(shù)聲明提升到作用域的頂層垢乙, // 這意味著我們的例子可以改寫成這樣: const example = function () { let declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; }; // 使用 const 和 let const example = function () { console.log(declaredButNotAssigned); // => throws a ReferenceError console.log(typeof declaredButNotAssigned); // => throws a ReferenceError const declaredButNotAssigned = true; };
-
11.2 <a name='11.2'></a> 匿名函數(shù)表達(dá)式的變量名會被提升,但函數(shù)內(nèi)容并不會语卤。
const example = function () { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function() { console.log('anonymous function expression'); }; };
-
11.3 <a name='11.3'></a> 命名的函數(shù)表達(dá)式的變量名會被提升追逮,但函數(shù)名和函數(shù)內(nèi)容并不會。
const example = function () { 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. const example = function () { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); } };
-
11.4 <a name='11.4'></a> 函數(shù)聲明的名稱和函數(shù)體都會被提升粹舵。
const example = function () { superPower(); // => Flying function superPower() { console.log('Flying'); } };
想了解更多信息钮孵,參考 Ben Cherry 的 JavaScript Scoping & Hoisting。
<a name="comparison-operators--equality"></a>
比較運(yùn)算符和等號
12.1 <a name='12.1'></a> 使用
===
和!==
而不是==
和!=
眼滤。eslint:eqeqeq
-
12.2 <a name='12.2'></a> 條件表達(dá)式例如
if
語句通過抽象方法ToBoolean
強(qiáng)制計算它們的表達(dá)式并且總是遵守下面的規(guī)則:- 對象 被計算為 true
- Undefined 被計算為 false
- Null 被計算為 false
- 布爾值 被計算為 布爾的值
- 數(shù)字 如果是 +0巴席、-0、或 NaN 被計算為 false, 否則為 true
-
字符串 如果是空字符串
''
被計算為 false诅需,否則為 true
if ([0] && []) { // true // an array (even an empty one) is an object, objects will evaluate to true }
-
12.3 <a name='12.3'></a> 布爾值使用簡寫漾唉,但是需要顯示比較字符串和數(shù)字。
// bad if (isValid === true) { // ... } // good if (isValid) { // ... } // bad if (name) { // ... } // good if (name !== '') { // ... } // bad if (collection.length) { // ... } // good if (collection.length > 0) { // ... }
12.4 <a name='12.4'></a> 想了解更多信息堰塌,參考 Angus Croll 的 Truth Equality and JavaScript赵刑。
<a name="comparison--switch-blocks"></a><a name="12.5"></a>
-
12.5 當(dāng)
case
和default
包含的子句中有詞法聲明時,用大括號包裹场刑。(例如let
,const
,function
, andclass
). eslint:no-case-declarations
為什么般此?詞法聲明在整個
switch
塊中是可見的,但只有在代碼執(zhí)行到case
中變量被賦值時才會被初始化摇邦,當(dāng)多個case
子句中定義相同的變量是時會出現(xiàn)問題恤煞。// bad switch (foo) { case 1: let xx = 1; break; case 2: const yy = 2; break; case 3: const func = function () { // ... }; break; default: get(); } // good switch (foo) { case 1: { let xx = 1; break; } case 2: { const yy = 2; break; } case 3: { const func = function () { // ... }; break; } case 4: bar(); break; default: { get(); } }
<a name="comparison--nested-ternaries"></a><a name="12.6"></a>
-
12.6 三元表達(dá)式不能嵌套使用屎勘。 eslint:
no-nested-ternary
// bad const foo = maybe1 > maybe2 ? "bar" : value1 > value2 ? "baz" : null; // split into 2 separated ternary expressions const maybeNull = value1 > value2 ? 'baz' : null; // better const foo = maybe1 > maybe2 ? 'bar' : maybeNull; // best const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
<a name="comparison--unneeded-ternary"></a><a name="12.7"></a>
-
12.7 避免出現(xiàn)不必要的三元表達(dá)式施籍。 eslint:
no-unneeded-ternary
// bad const foo = maybe1 ? maybe1 : maybe2; const bar = correct ? true : false; const baz = wrong ? false : true; // good const foo = maybe1 || maybe2; const bar = !!correct; const baz = !wrong;
<a name="comparison--no-mixed-operators"></a>
-
12.8 當(dāng)混用操作符時,要用括號括起來概漱。唯一的例外是標(biāo)準(zhǔn)的算術(shù)運(yùn)算符 (
+
,-
,*
, &/
)丑慎,因為它們很容易理解。 eslint:no-mixed-operators
為什么?這提高了代碼的可讀性竿裂,并且使得開發(fā)者的意圖很清晰玉吁。
// bad const foo = p1 && p2 < 0 || p3 > 0 || p4 + 1 === 0; // bad const bar = p1 ** p2 - 5 % p4; // bad // one may be confused into thinking (p1 || p2) && p3 if (p1 || p2 && p3) { return p4; } // good const foo = (p1 && p2 < 0) || p3 > 0 || (p4 + 1 === 0); // good const bar = (p1 ** p2) - (5 % p4); // good if (p1 || (p2 && p3)) { return p4; } // good const bar = p1 + (p2 / p3 * p4);
<a name="blocks"></a>
代碼塊 Blocks
-
13.1 <a name='13.1'></a> 使用大括號包裹所有的多行代碼塊。eslint:
nonblock-statement-body-position
// bad if (test) return false; // good if (test) { return false; } // good if (test) { return false; } // bad const func = function () {return false}; // good const func = function () { return false; };
-
13.2 <a name='13.2'></a> 如果通過
if
和else
使用多行代碼塊腻异,把else
放在if
代碼塊關(guān)閉括號的同一行进副。eslint:brace-style
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
<a name="blocks--no-else-return"></a><a name="13.3"></a>
-
13.3 如果
if
代碼塊中肯定會執(zhí)行return
語句,那么后面的else
就沒必要寫了悔常。如果在else if
代碼塊中又有if
影斑,并且if
代碼塊會執(zhí)行return
語句,那么可以分拆成多個if
代碼塊机打。 eslint:no-else-return
// bad const foo = function () { if (correct) { return correct; } else { return wrong; } }; // bad const cats = function () { if (correct) { return correct; } else if (wrong) { return wrong; } }; // bad const dogs = function () { if (correct) { return correct; } else { if (wrong) { return wrong; } } }; // good const foo = function () { if (correct) { return correct; } return wrong; }; // good const cats = function () { if (correct) { return correct; } if (wrong) { return wrong; } return false; }; //good const dogs = function (correct) { if (correct) { if (confuse) { return wrong; } } else { return confuse; } };
<a name="comments"></a>
注釋 Comments
-
14.1 <a name='14.1'></a> 所有的注釋開頭都加一個空格矫户,這樣更利于閱讀。eslint:
spaced-comment
// bad //is current tab const active = true; // good // is current tab const active = true; // bad /** *make() returns a new element *based on the passed-in tag name */ const make = function (tag) { // ... return element; }; // good /** * make() returns a new element * based on the passed-in tag name */ const make = function (tag) { // ... return element; };
14.2 <a name='14.2'></a> 給注釋增加
FIXME
或TODO
的前綴可以幫助其他開發(fā)者快速了解這是一個需要復(fù)查的問題残邀,或是給需要實現(xiàn)的功能提供一個解決方式皆辽。這將有別于常見的注釋,因為它們是可操作的芥挣。使用FIXME -- need to figure this out
或者TODO -- need to implement
驱闷。-
14.3 <a name='14.3'></a> 使用
// FIXME
: 標(biāo)注問題。class Calculator { constructor() { // FIXME: shouldn't use a global here total = 0; } }
-
14.4 <a name='14.4'></a> 使用
// TODO
: 標(biāo)注問題的解決方式空免。class Calculator { constructor() { // TODO: total should be configurable by an options param this.total = 0; } }
<a name="whitespace"></a>
空格 Whitespace
-
15.1 <a name='15.1'></a> 使用 4 個空格作為縮進(jìn)遗嗽。eslint:
indent
// bad const func = function () { ??const name = ''; } // bad const func = function () { ?const name = ''; } // good const func = function () { ????const name = ''; }
-
15.2 <a name='15.2'></a> 在大括號前放一個空格。eslint:
space-before-blocks
// bad const test = function (){ console.log('test'); } // good const test = function () { 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', });
-
15.3 <a name='15.3'></a> 在控制語句(
if
鼓蜒、while
等)的小括號前放一個空格痹换。在函數(shù)調(diào)用及聲明中,不要在函數(shù)的參數(shù)列表前加空格都弹。eslint:keyword-spacing
// bad if(isJedi) { fight (); } // good if (isJedi) { fight(); } // bad const fight = function() { console.log ('Swooosh!'); } // good const fight = function () { console.log('Swooosh!'); }
-
15.4 <a name='15.4'></a> 使用空格把運(yùn)算符隔開娇豫。eslint:
space-infix-ops
// bad const i=j+5; // good const i = j + 5;
-
15.5 <a name='15.5'></a> 在文件末尾插入一個空行。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;?
-
15.6 <a name='15.6'></a> 在使用長方法鏈時進(jìn)行縮進(jì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').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); // good const leds = stage.selectAll('.led').data(data);
-
15.7 <a name='15.7'></a> 在塊末和新語句前插入空行。
// 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;
<a name="whitespace--padded-blocks"></a><a name="15.8"></a>
-
15.8 不要在 block 代碼塊中加空行框杜。 eslint:
padded-blocks
// bad const bar = function () { console.log(foo); }; // bad if (baz) { console.log(qux); } else { console.log(foo); } // bad class Foo { constructor(bar) { this.bar = bar; } } // good const bar = function () { console.log(foo); }; // good if (baz) { console.log(qux); } else { console.log(foo); }
<a name="whitespace--in-parens"></a><a name="15.9"></a>
-
15.9 不要在小括號中加空格浦楣。 eslint:
space-in-parens
// bad const bar = function ( foo ) { return foo; }; // good const bar = function (foo) { return foo; }; // bad if ( foo ) { console.log(foo); } // good if (foo) { console.log(foo); }
<a name="whitespace--in-brackets"></a><a name="15.10"></a>
-
15.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="whitespace--in-braces"></a><a name="15.11"></a>
-
15.11 不要在大括號中加空格咪辱。 eslint:
object-curly-spacing
// bad const foo = { clark: 'kent' }; // good const foo = {clark: 'kent'};
<a name="whitespace--max-len"></a><a name="15.12"></a>
-
15.12 盡量控制一行代碼在==100==個字符以內(nèi)(包括空格)振劳。字符串、字符串模板和 URL 不受限制油狂。eslint:
max-len
為什么历恐?這么做保證了可讀性和可維護(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(() => { // do something... }) .fail(() => { // do something... });
<a name="commas"></a>
逗號 Commas
-
16.1 <a name='16.1'></a> 行首逗號:禁用。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', };
-
16.2 <a name='16.2'></a> 增加結(jié)尾的逗號:需要弱贼。eslint:
comma-dangle
為什么? 這會讓 git diffs 更干凈蒸苇。另外,像 babel 這樣的轉(zhuǎn)譯器會移除結(jié)尾多余的逗號吮旅,也就是說你不必?fù)?dān)心老舊瀏覽器的尾逗號問題溪烤。
// 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', ]; // bad const createHero = function ( firstName, lastName, inventorOf ) { // does nothing }; // good const createHero = function ( firstName, lastName, inventorOf, ) { // does nothing }; // good (note that a comma must not appear after a "rest" element) const createHero = function ( firstName, lastName, inventorOf, ...heroArgs ) { // does nothing }; // bad createHero( firstName, lastName, inventorOf ); // good createHero( firstName, lastName, inventorOf, ); // good createHero( firstName, lastName, inventorOf, ...heroArgs );
<a name="semicolons"></a>
分號 Semicolons
-
17.1 <a name='17.1'></a> 使用分號。eslint:
semi
Why? When JavaScript encounters a line break without a semicolon, it uses a set of rules called Automatic Semicolon Insertion to determine whether or not it should regard that line break as the end of a statement, and (as the name implies) place a semicolon into your code before the line break if it thinks so. ASI contains a few eccentric behaviors, though, and your code will break if JavaScript misinterprets your line break. These rules will become more complicated as new features become a part of JavaScript. Explicitly terminating your statements and configuring your linter to catch missing semicolons will help prevent you from encountering issues.
// bad - raises exception const luke = {} const leia = {} [luke, leia].forEach(jedi => jedi.father = 'vader') // bad - raises exception const reaction = "No! That's impossible!" (async function meanwhileOnTheFalcon(){ // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` // ... }()) // bad - returns `undefined` instead of the value on the next line - always happens when `return` is on a line by itself because of ASI! const foo = foo() { return 'search your feelings, you know it to be foo' }; // good const luke = {}; const leia = {}; [luke, leia].forEach((jedi) => { jedi.father = 'vader'; }); // good const reaction = "No! That's impossible!"; (async function meanwhileOnTheFalcon(){ // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` // ... }()); // good const foo = foo() { return 'search your feelings, you know it to be foo'; };
<a name="type-casting--coercion"></a>
類型轉(zhuǎn)換
18.1 <a name='18.1'></a> 在語句開始時執(zhí)行類型轉(zhuǎn)換庇勃。
-
18.2 <a name='18.2'></a> 字符串: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(); // isn’t guaranteed to return a string // good const totalScore = String(this.reviewScore);
-
18.3 <a name='18.3'></a> 對數(shù)字使用
parseInt
轉(zhuǎn)換氛什,并帶上類型轉(zhuǎn)換的基數(shù)。(不強(qiáng)制)eslint:radix
no-new-wrappers
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);
-
18.4 <a name='18.4'></a> 如果因為某些原因 parseInt 成為你所做的事的瓶頸而需要使用位操作解決性能問題時匪凉,留個注釋說清楚原因和你的目的枪眉。
// good /** * 使用 parseInt 導(dǎo)致我的程序變慢, * 改成使用位操作轉(zhuǎn)換數(shù)字快多了再层。 */ const val = inputValue >> 0;
-
18.5 <a name='18.5'></a> 注: 小心使用位操作運(yùn)算符贸铜。數(shù)字會被當(dāng)成 64 位值,但是位操作運(yùn)算符總是返回 32 位的整數(shù)(參考)聂受。位操作處理大于 32 位的整數(shù)值時還會導(dǎo)致意料之外的行為蒿秦。關(guān)于這個問題的討論。最大的 32 位整數(shù)是 2,147,483,647:
2147483647 >> 0 //=> 2147483647 2147483648 >> 0 //=> -2147483648 2147483649 >> 0 //=> -2147483647
-
18.6 <a name='18.6'></a> 布爾:eslint:
no-new-wrappers
const age = 0; // bad const hasAge = new Boolean(age); // good const hasAge = Boolean(age); // good const hasAge = !!age;
<a name="naming-conventions"></a>
命名規(guī)則
-
19.1 <a name='19.1'></a> 避免單字母命名(
e蛋济、i棍鳖、j、v碗旅、k渡处、t除外
)。避免超長變量名(長度不超過60)祟辟。命名應(yīng)具備描述性和可讀性医瘫。eslint:id-length
// bad const q = function () { // ...stuff... }; // bad const getWebBeibei11MaylikeRecommendPageSize20Page1XidMTcxNTM2Njcxsa = function () { // ...stuff... }; // good const query = function () { // ...stuff..。 };
-
19.2 <a name='19.2'></a> 使用駝峰式命名對象旧困、函數(shù)和實例醇份。(對象的屬性不限制)eslint:
camelcase
// bad const OBJEcttsssss = {}; const this_is_my_object = {}; // good const thisIsMyObject = {}; const thisIsMyFunction = function () {}
-
19.3 <a name='19.3'></a> 使用帕斯卡式命名構(gòu)造函數(shù)或類。eslint:
new-cap
// 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', });
-
19.4 <a name='19.4'></a> 別保存
this
的引用吼具。使用箭頭函數(shù)或 Function#bind僚纷。// bad const foo = function () { const self = this; return function() { console.log(self); }; }; // bad const foo = function () { const that = this; return function() { console.log(that); }; }; // good const foo = function () { return () => { console.log(this); }; };
-
19.5 <a name='19.5'></a> 如果你的文件只輸出一個類,那你的文件名必須和類名完全保持一致拗盒。
// 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';
-
19.6 <a name='19.6'></a> 當(dāng)你導(dǎo)出默認(rèn)的函數(shù)時使用駝峰式命名怖竭。你的文件名必須和函數(shù)名完全保持一致。
const makeStyleGuide = function () { } export default makeStyleGuide;
-
19.7 <a name='19.7'></a> 當(dāng)你導(dǎo)出單例锣咒、函數(shù)庫侵状、空對象時使用帕斯卡式命名赞弥。
const AirbnbStyleGuide = { es6: { } }; export default AirbnbStyleGuide;