# å端代ç è§è â JavaScript 飿 ¼æå ## åè¨ æ¬æåºäº github é¡¹ç® [airbnb/javascript](https://github.com/airbnb/javascript#types) ç¿»è¯ï¼ä¹å å ¥äºä¸äºä¸ªäººçè§£ãè§èæå©äºæä»¬æ´å¥½çæé«ä»£ç å¯è¯»æ§ï¼é¿å ä¸äºä¸å¿ è¦ç bugã使¯ï¼å¹¶æ²¡æç»ä¸çæ åå硬æ§è¦æ±ï¼è¿éåªæ¯ç»å¤§å®¶æä¾ä¸äºåèï¼éåå¢éåèªå·±çææ¯æå¥½çã **个人å客å°å [ð¹ð° fe-code](https://github.com/wuyawei/fe-code)** ## ç±»å * 1.1 åºæ¬ç±»å > åºæ¬ç±»åèµå¼æ¶ï¼åºè¯¥ç´æ¥ä½¿ç¨ç±»åçå¼ * `string` * `number` * `boolean` * `null` * `undefined` * `symbol` ```javascript const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1,9 ``` * å¤æç±»å > å¤æç±»åèµå¼å ¶å®æ¯å°åçå¼ç¨ * `object` * `array` * `function` ```javascript const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9 // const åªè½é»æ¢å¼ç¨ç±»åå°åçéæ°èµå¼ // å¹¶ä¸è½ä¿è¯å¼ç¨ç±»åç屿§çä¸å ``` ## ç¶æç使ç¨ï¼åæä¸º Referenceï¼ * 2.1 ææçèµå¼é½ç¨`const`ï¼é¿å 使ç¨`var`. eslint: [`prefer-const`](http://eslint.org/docs/rules/prefer-const.html), [`no-const-assign`](http://eslint.org/docs/rules/no-const-assign.html) > å°½éç¡®ä¿ä½ ç代ç ä¸çç¶ææ¯å¯æ§èå´å çï¼éå¤å¼ç¨ä¼åºç°é¾ä»¥çè§£ç bug å代ç ã ```javascript // bad var a = 1; var b = 2; // good const a = 1; const b = 2; ``` * 2.2 å¦æä½ ä¸å®è¦å¯¹åæ°éæ°èµå¼ï¼é£å°±ç¨`let`ï¼è䏿¯`var`. eslint: [`no-var`](http://eslint.org/docs/rules/no-var.html) > `let`æ¯å级ä½ç¨åï¼`var`æ¯å½æ°çº§ä½ç¨åï¼åæ ·æ¯ä¸ºäºåå°ä»£ç çä¸å¯æ§ï¼åå° âæå¤â ```javascript // bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; } ``` * 2.3 `let`ã`const`齿¯å级ä½ç¨å ```javascript // const å let é½åªåå¨äºå®å®ä¹çé£ä¸ªå级ä½ç¨å { let a = 1; const b = 1; } console.log(a); // ReferenceError console.log(b); // ReferenceError ``` ## 对象 * 3.1 使ç¨åé¢å¼å建对象. eslint: [`no-new-object`](http://eslint.org/docs/rules/no-new-object.html) ```javascript // bad const item = new Object(); // good const item = {}; ``` * 3.2 å½å建ä¸ä¸ªå¸¦æå¨æå±æ§åç对象æ¶ï¼å°å®ä¹çææå±æ§æ¾å¨å¯¹è±¡çä¸ä¸ªå°æ¹ã ```javascript function getKey(k) { return `a key named ${k}`; } // bad const obj = { id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true; // good getKey('enabled')æ¯å¨æå±æ§å const obj = { id: 5, name: 'San Francisco', [getKey('enabled')]: true, }; ``` * 3.3 æ¹æ³ç®å. eslint: [`object-shorthand`](http://eslint.org/docs/rules/object-shorthand.html) ```javascript // bad const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // good const atom = { value: 1, // å¯¹è±¡çæ¹æ³ addValue(value) { return atom.value + value; }, }; ``` * 3.4 屿§å¼ç¼©å. eslint: [`object-shorthand`](http://eslint.org/docs/rules/object-shorthand.html) ```javascript const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker }; ``` * 3.5 å°å±æ§çç¼©åæ¾å¨å¯¹è±¡å£°æçå¼å¤´ã ```javascript 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, }; ``` * 3.6 åªå¯¹é£äºæ æçæ 示使ç¨å¼å· `''`. eslint: [`quote-props`](http://eslint.org/docs/rules/quote-props.html) > ä¸è¬æ¥è¯´ï¼æä»¬è®¤ä¸ºå®å¨ä¸»è§ä¸æ´å®¹æé 读ã宿¹è¿äºè¯æ³çªåºæ¾ç¤ºï¼å¹¶ä¸æ´å®¹æè¢«JS弿ä¼åã ```javascript // bad const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // good const good = { foo: 3, bar: 4, 'data-blah': 5, }; ``` * 3.7 ä¸è¦ç´æ¥è°ç¨`Object.prototype`ä¸çæ¹æ³ï¼å¦`hasOwnProperty`, `propertyIsEnumerable`, `isPrototypeOf`ã > å¨ä¸äºæé®é¢ç对象ä¸ï¼ è¿äºæ¹æ³å¯è½ä¼è¢«å±è½æ - å¦ï¼`{ hasOwnProperty: false }` - æè¿æ¯ä¸ä¸ªç©ºå¯¹è±¡`Object.create(null)` ```javascript // bad console.log(object.hasOwnProperty(key)); // good console.log(Object.prototype.hasOwnProperty.call(object, key)); // best const has = Object.prototype.hasOwnProperty; // 卿¨¡åä½ç¨å å䏿¬¡ç¼å /* or */ import has from 'has'; // https://www.npmjs.com/package/has // ... console.log(has.call(object, key)); ``` * 3.8 å¯¹è±¡æµ æ·è´æ¶ï¼æ´æ¨èä½¿ç¨æ©å±è¿ç®ç¬¦ `...`ï¼è䏿¯[`Object.assign`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)ãè§£æèµå¼è·å对象æå®çå ä¸ªå±æ§æ¶ï¼æ¨èç¨ rest è¿ç®ç¬¦ï¼ä¹æ¯ `...`ã ```javascript // very bad const original = { a: 1, b: 2 }; const copy = Object.assign(original, { c: 3 }); delete copy.a; // so does this æ¹åäº original // bad const original = { a: 1, b: 2 }; const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 } // good const 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 } ``` ## æ°ç» * 4.1 ç¨åé¢éèµå¼ã eslint: [`no-array-constructor`](http://eslint.org/docs/rules/no-array-constructor.html) ```javascript // bad const items = new Array(); // good const items = []; ``` * 4.2 ç¨[Array#push](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/push) åæ°ç»ä¸æ·»å ä¸ä¸ªå¼è䏿¯ç´æ¥ç¨ä¸æ ã ```javascript const someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra'); ``` * 4.3 ç¨æ©å±è¿ç®ç¬¦åæ°ç»æµ æ·è´ï¼ç±»ä¼¼ä¸é¢çå¯¹è±¡æµ æ·è´ ```javascript // bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i += 1) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items]; ``` * 4.4 æ¨èç¨ `...` è¿ç®ç¬¦è䏿¯[`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from)æ¥å°ä¸ä¸ªç±»æ°ç»è½¬æ¢ææ°ç»ã ```javascript const foo = document.querySelectorAll('.foo'); // good const nodes = Array.from(foo); // best const nodes = [...foo]; ``` * 4.5 ç¨ [`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from) å»å°ä¸ä¸ªç±»æ°ç»å¯¹è±¡è½¬æä¸ä¸ªæ°ç»ã ```javascript const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; // bad const arr = Array.prototype.slice.call(arrLike); // good const arr = Array.from(arrLike); ``` * 4.6 ç¨ [`Array.from`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from) è䏿¯ `...` è¿ç®ç¬¦å»è¿ä»£ã è¿æ ·å¯ä»¥é¿å å建ä¸ä¸ªä¸é´æ°ç»ã ```javascript // bad const baz = [...foo].map(bar); // good const baz = Array.from(foo, bar); ``` * 4.7 卿°ç»æ¹æ³çåè°å½æ°ä¸ä½¿ç¨ return è¯å¥ã 妿彿°ä½ç±ä¸æ¡è¿åä¸ä¸ªè¡¨è¾¾å¼çè¯å¥ç»æï¼ å¹¶ä¸è¿ä¸ªè¡¨è¾¾å¼æ²¡æå¯ä½ç¨ï¼ è¿ä¸ªæ¶åå¯ä»¥å¿½ç¥returnï¼è¯¦è§ [8.2](#arrows--implicit-return). eslint: [`array-callback-return`](http://eslint.org/docs/rules/array-callback-return) ```javascript // good [1, 2, 3].map((x) => { const y = x + 1; return x * y; }); // good 彿°åªæä¸ä¸ªè¯å¥ [1, 2, 3].map(x => x + 1); // bad 没æè¿åå¼ï¼ 导è´å¨ç¬¬ä¸æ¬¡è¿ä»£åacc å°±åæundefinedäº [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => { const flatten = acc.concat(item); acc[index] = flatten; }); // good [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => { const flatten = acc.concat(item); acc[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; }); ``` * 4.8 妿ä¸ä¸ªæ°ç»æå¾å¤è¡ï¼å¨æ°ç»ç `[` åå `]` 忢è¡ã ```javascript // 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, ]; ``` ## è§£æ * 5.1 ç¨å¯¹è±¡çè§£æèµå¼æ¥è·åå使ç¨å¯¹è±¡æä¸ªæå¤ä¸ªå±æ§å¼ã eslint: [`prefer-destructuring`](https://eslint.org/docs/rules/prefer-destructuring) > è¿æ ·å°±ä¸éè¦ç»è¿äºå±æ§å建临æ¶/å¼ç¨ ```javascript // 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}`; } ``` * 5.2 æ°ç»è§£æ. ```javascript const arr = [1, 2, 3, 4]; // bad const first = arr[0]; const second = arr[1]; // good const [first, second] = arr; ``` * 5.3 å¤ä¸ªè¿åå¼ç¨å¯¹è±¡çè§£æï¼è䏿¯æ°ç»è§£æã > ä¸ä¾èµäºè¿åå¼ç顺åºï¼æ´å¯è¯» ```javascript // bad function processInput(input) { // ç¶åå°±æ¯è§è¯å¥è¿¹çæ¶å» return [left, right, top, bottom]; } const [left, __, top] = processInput(input); // good function processInput(input) { return { left, right, top, bottom }; } const { left, top } = processInput(input); ``` ## å符串 * 6.1 string ç»ä¸ç¨åå¼å· `''` ã eslint: [`quotes`](https://eslint.org/docs/rules/quotes.html) ```javascript // bad const name = "Capt. Janeway"; // bad - 模æ¿åºè¯¥å å«æå ¥æåææ¢è¡ const name = `Capt. Janeway`; // good const name = 'Capt. Janeway'; ``` * 6.2 ä¸åºè¯¥ç¨ `+` è¿æ¥æ¢è¡å符串ã > ä¸å¥½ç¨ï¼ä¸å¯è¯»æ§å·® ```javascript // 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.'; ``` * 6.3 ç¨å符串模æ¿è䏿¯ `+` æ¥æ¼æ¥å符串ã eslint: [`prefer-template`](https://eslint.org/docs/rules/prefer-template.html) [`template-curly-spacing`](https://eslint.org/docs/rules/template-curly-spacing) > 模æ¿å符串æ´å ·å¯è¯»æ§ãè¯æ³ç®æ´ãå符串æå ¥åæ°ã ```javascript // 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}?`; } ``` * 6.4 æ°¸è¿ä¸è¦å¨å符串ä¸ç¨`eval()`ï¼æ¼æ´å¤ªå¤ã eslint: [`no-eval`](https://eslint.org/docs/rules/no-eval) - [6.5](#strings--escaping) ä¸è¦ä½¿ç¨ä¸å¿ è¦ç转ä¹å符ãeslint: [`no-useless-escape`](http://eslint.org/docs/rules/no-useless-escape) > åæçº¿å¯è¯»æ§å·®ï¼åªå¨å¿ è¦æ¶ä½¿ç¨ ```javascript // bad const foo = '\'this\' \i\s \"quoted\"'; // good const foo = '\'this\' is "quoted"'; //best const foo = `my name is '${name}'`; ``` ## 彿° * 7.1 ç¨å½å彿°è¡¨è¾¾å¼è䏿¯å½æ°å£°æãeslint: [`func-style`](http://eslint.org/docs/rules/func-style) > 彿°å£°æä½ç¨å伿åï¼éä½äºä»£ç å¯è¯»æ§åå¯ç»´æ¤æ§ãå¦æä½ åç°ä¸ä¸ªå½æ°å大å夿ï¼è¿ä¸ªå½æ°å¦¨ç¢è¿ä¸ªæä»¶å ¶ä»é¨åççè§£æ§ï¼è¿å¯è½å°±æ¯æ¶åæè¿ä¸ªå½æ°åç¬æ½æä¸ä¸ªæ¨¡åäºã([Discussion](https://github.com/airbnb/javascript/issues/794)) ```javascript // bad function foo() { // ... } // bad const foo = function () { // ... }; // good const short = function longUniqueMoreDescriptiveLexicalFoo() { // ... }; ``` * 7.2 æç«å³æ§è¡å½æ°å 裹å¨åæ¬å·éã eslint: [`wrap-iife`](http://eslint.org/docs/rules/wrap-iife.html) > ä¸ä¸ªç«å³è°ç¨ç彿°è¡¨è¾¾å¼æ¯ä¸ä¸ªåå - æå®åä»çè°ç¨è ï¼åæ¬å·ï¼å 裹起æ¥ãå½ç¶ï¼ç°ä»£æ¨¡åå¼åä¸ï¼ä½ åºæ¬ç¨ä¸å°ã ```javascript // immediately-invoked function expression (IIFE) (function () { console.log('Welcome to the Internet. Please follow me.'); }()); ``` * 7.3 ä¸è¦å¨é彿°åï¼ifãwhileççï¼å 声æå½æ°ãèæ¯æè¿ä¸ªå½æ°åé ç»ä¸ä¸ªåéãæµè§å¨ä¼å è®¸ä½ è¿æ ·åï¼ä½æµè§å¨è§£ææ¹å¼ä¸åï¼ç»æä¹è®¸ä¼æå·®å¼ãã详è§`no-loop-func`ã eslint: [`no-loop-func`](http://eslint.org/docs/rules/no-loop-func.html) * 7.4 **注æ:** å¨ECMA-262ä¸ [å `block`] çå®ä¹æ¯ï¼ ä¸ç³»åçè¯å¥ï¼ 使¯å½æ°å£°æä¸æ¯ä¸ä¸ªè¯å¥ã 彿°è¡¨è¾¾å¼æ¯ä¸ä¸ªè¯å¥ã ```javascript // bad if (currentUser) { function test() { console.log('Nope.'); } } // good let test; if (currentUser) { test = () => { console.log('Yup.'); }; } ``` * 7.5 æ°¸è¿ä¸è¦ç¨`arguments`å½ååæ°ãå®çä¼å 级é«äºæ¯ä¸ªå½æ°ä½ç¨åèªå¸¦ç `arguments` å¯¹è±¡ï¼ æä»¥ä¼å¯¼è´å½æ°èªå¸¦ç `arguments` å¼è¢«è¦çã ```javascript // bad function foo(name, options, arguments) { // ... } // good function foo(name, options, args) { // ... } ``` * 7.6 ä¼å 使ç¨restè¯æ³`...`ï¼è䏿¯ `arguments`ã eslint: [`prefer-rest-params`](http://eslint.org/docs/rules/prefer-rest-params) > `...` æ´æç¡®ä½ æ³ç¨åªäºåæ°ã ```javascript // bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function concatenateAll(...args) { return args.join(''); } ``` * 7.8 使ç¨é»è®¤åæ°è¯æ³ï¼è䏿¯å¨å½æ°é坹忰鿰èµå¼ã ```javascript // really bad function handleThings(opts) { // è½ç¶ä½ æ³è¿ä¹åï¼ ä½æ¯è¿ä¸ªä¼å¸¦æ¥ä¸äºç»å¾®çbug // 妿 opts çå¼ä¸º false, å®ä¼è¢«èµå¼ä¸º {} opts = opts || {}; // ... } // still bad function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // good function handleThings(opts = {}) { // ... } ``` * 7.8 使ç¨é»è®¤åæ°æ¶ï¼éè¦é¿å å¯ä½ç¨ ```javascript var b = 1; // bad function count(a = b++) { console.log(a); } count(); // 1 count(); // 2 count(3); // 3 count(); // 3 // å¾å®¹æè®©äººæµé¼ ``` * 7.9 æé»è®¤åæ°èµå¼æ¾å¨æå ```javascript // bad function handleThings(opts = {}, name) { // ... } // good function handleThings(name, opts = {}) { // ... } ``` * 7.10 ä¸è¦ç¨ Function åå»ºå½æ°ã eslint: [`no-new-func`](http://eslint.org/docs/rules/no-new-func) ```javascript // bad var add = new Function('a', 'b', 'return a + b'); // still bad var subtract = Function('a', 'b', 'return a - b'); ``` * 7.11 彿°ç¾åé¨åè¦æç©ºæ ¼ãeslint: [`space-before-function-paren`](http://eslint.org/docs/rules/space-before-function-paren) [`space-before-blocks`](http://eslint.org/docs/rules/space-before-blocks) ```javascript // bad const f = function(){}; const g = function (){}; const h = function() {}; // good const x = function () {}; const y = function a() {}; ``` * 7.12 æ°¸è¿ä¸è¦æ¹åæ°. eslint: [`no-param-reassign`](http://eslint.org/docs/rules/no-param-reassign.html) > ç¹å«æ³¨æå¼ç¨ç±»åçæä½ï¼ä¿è¯æ°æ®çä¸å¯åæ§ ```javascript // bad function f1(obj) { obj.key = 1; }; // good function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; }; ``` * 7.13 ä¸è¦å¯¹åæ°éæ°èµå¼ã eslint: [`no-param-reassign`](http://eslint.org/docs/rules/no-param-reassign.html) ```javascript // 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) { // ... } ``` * 7.14 æ´»ç¨ `...`ã eslint: [`prefer-spread`](http://eslint.org/docs/rules/prefer-spread) > Why? è¿æ ·æ´æ¸ æ°ï¼ä½ ä¸å¿ æä¾ä¸ä¸æï¼èä¸ä½ ä¸è½è½»æå°ç¨`apply`æ¥ç»æ`new` ```javascript // 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]); ``` * 7.15 å¤ä¸ªåæ°ç彿°åºè¯¥åè¿ä¸ªæåéçå ¶ä»å¤è¡ä»£ç 忳䏿 ·ï¼ æ¯è¡åªæä¸ä¸ªåæ°ï¼æ¯è¡éå·ç»å°¾ã ```javascript // bad function foo(bar, baz, quux) { // ... } // good function foo( bar, baz, quux, ) { // ... } // bad console.log(foo, bar, baz); // good console.log( foo, bar, baz, ); ``` ## ç®å¤´å½æ° * 8.1 妿è¦ç¨å¿å彿°ååè°ï¼æå¥½ä½¿ç¨ç®å¤´å½æ° eslint: [`prefer-arrow-callback`](http://eslint.org/docs/rules/prefer-arrow-callback.html), [`arrow-spacing`](http://eslint.org/docs/rules/arrow-spacing.html) > å®å建äºä¸ä¸ªå¨ä¸ä¸æä¸æ§è¡ç彿°ï¼è¿éå¸¸æ¯æ¨æ³è¦çï¼å¹¶ä¸æ¯ä¸ç§æ´ç®æ´çè¯æ³ã ```javascript // bad [1, 2, 3].map(function (x) { const y = x + 1; return x * y; }); // good [1, 2, 3].map((x) => { const y = x + 1; return x * y; }); ``` * 8.2 妿彿°ä½ç±ä¸ä¸ªæ²¡æå¯ä½ç¨ç[表达å¼](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions)çå个è¯å¥ç»æï¼å»æå¤§æ¬å·å returnãå¦åï¼ä¿ç大æ¬å·ä¸ä½¿ç¨ `return` è¯å¥ã eslint: [`arrow-parens`](https://eslint.org/docs/rules/arrow-parens.html), [`arrow-body-style`](https://eslint.org/docs/rules/arrow-body-style.html) ```javascript // 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 })); // è¡¨è¾¾å¼æå¯ä½ç¨å°±ä¸è¦ç¨éå¼è¿å function foo(callback) { const val = callback(); if (val === true) { // Do something if callback returns true } } let bool = false; // bad foo(() => bool = true); // good foo(() => { bool = true; }); ``` * 8.3 å¦æè¡¨è¾¾å¼æå¤è¡ï¼é¦å°¾æ¾å¨åæ¬å·éæ´å¯è¯»ã ```js // bad ['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod ) ); // good ['get', 'post', 'put'].map(httpMethod => ( Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod ) )); ``` * 8.4 ä¸ºäºæ¸ æ°åä¸è´ï¼å§ç»å¨åæ°å¨å´å 䏿¬å· eslint: [`arrow-parens`](https://eslint.org/docs/rules/arrow-parens.html) ```js // bad [1, 2, 3].map((x) => x * x); // good [1, 2, 3].map(x => x * x); // good [1, 2, 3].map(number => ( `A long string with the ${number}. Itâs so long that we donât want it to take up space on the .map line!` )); // bad [1, 2, 3].map(x => { const y = x + 1; return x * y; }); // good [1, 2, 3].map((x) => { const y = x + 1; return x * y; }); ``` - [8.5](#arrows--confusing) é¿å ç®å¤´å½æ°è¯æ³ `=>` åæ¯è¾æä½ç¬¦ `<=, >=` æ··æ·. eslint: [`no-confusing-arrow`](http://eslint.org/docs/rules/no-confusing-arrow) ```js // bad const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize; // bad const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize; // good const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize); // good const itemHeight = (item) => { const { height, largeSize, smallSize } = item; return height > 256 ? largeSize : smallSize; }; ``` * 8.6 使ç¨éå¼è¿åæ¶å¼ºå¶çº¦æå½æ°ä½å¨ç®å¤´åé¢ã eslint: [`implicit-arrow-linebreak`](https://eslint.org/docs/rules/implicit-arrow-linebreak) ```javascript // bad (foo) => bar; (foo) => (bar); // good (foo) => bar; (foo) => (bar); (foo) => ( bar ) ``` ## ç±»åæé 彿° * 9.1 å§ç»ç¨`class`ï¼é¿å ç´æ¥æä½`prototype` ```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; } } ``` * 9.2 使ç¨`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`æ¥å®ç°æ¹æ³é¾ ```javascript // 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() æ¹æ³ï¼ä½æ¯è¦ä¿è¯å®æ¯å¯ä»¥æ£å¸¸å·¥ä½ä¸æ²¡æå¯ä½ç¨ ```javascript class Jedi { constructor(options = {}) { this.name = options.name || 'no name'; } getName() { return this.name; } toString() { return `Jedi - ${this.getName()}`; } } ``` * 9.5 å¦ææ²¡æç¹æ®è¯´æï¼ç±»æé»è®¤çæé æ¹æ³ãä¸ç¨ç¹æåä¸ä¸ªç©ºçæé 彿°æåªæ¯ä»£è¡¨ç¶ç±»çæé 彿°ã eslint: [`no-useless-constructor`](http://eslint.org/docs/rules/no-useless-constructor) ```javascript // bad class Jedi { constructor() {} getName() { return this.name; } } // bad class Rey extends Jedi { // è¿ç§æé 彿°æ¯ä¸éè¦åç constructor(...args) { super(...args); } } // good class Rey extends Jedi { constructor(...args) { super(...args); this.name = 'Rey'; } } ``` * 9.6 é¿å éå¤ç±»çæåã eslint: [`no-dupe-class-members`](http://eslint.org/docs/rules/no-dupe-class-members) > éå¤ç±»æåä¼é»é»çæ§è¡æåä¸ä¸ªï¼æéå¤è¯å®å°±æ¯ä¸ä¸ªé误 ```javascript // bad class Foo { bar() { return 1; } bar() { return 2; } } // good class Foo { bar() { return 1; } } // good class Foo { bar() { return 2; } } ``` ## 模å * 10.1 å¨éæ 忍¡åç³»ç»ä¸ä½¿ç¨(`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; ``` * 10.2 ä¸è¦ç¨ import * è¿ç§éé 符 ```javascript // bad import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // good import AirbnbStyleGuide from './AirbnbStyleGuide'; ``` * 10.3 ä¸è¦ç´æ¥ä» import ä¸ç´æ¥ export > çèµ·æ¥ç®æ´ï¼ä½æ¯å½±åå¯è¯»æ§ ```javascript // bad // filename es6.js export { es6 as default } from './AirbnbStyleGuide'; // good // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6; ``` * 10.4 ä¸ä¸ªå ¥å£åª import 䏿¬¡ã eslint: [`no-duplicate-imports`](http://eslint.org/docs/rules/no-duplicate-imports) > Why? ä»åä¸ä¸ªè·¯å¾ä¸importå¤è¡ä¼ä½¿ä»£ç é¾ä»¥ç»´æ¤ ```javascript // 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'; ``` * 10.5 ä¸è¦å¯¼åºå¯åçç»å® eslint: [`import/no-mutable-exports`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-mutable-exports.md) > å°½éåå°ç¶æï¼ä¿è¯æ°æ®çä¸å¯åæ§ãè½ç¶å¨æäºåºæ¯ä¸å¯è½éè¦è¿ç§ææ¯ï¼ä½æ»çæ¥è¯´åºè¯¥å¯¼åºå¸¸éã ```javascript // bad let foo = 3; export { foo } // good const foo = 3; export { foo } ``` * 10.6 å¨åªæä¸ä¸ªå¯¼åºç模åéï¼ç¨ `export default` æ´å¥½ã eslint: [`import/prefer-default-export`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/prefer-default-export.md) > é¼å±ä½¿ç¨æ´å¤æä»¶ï¼æ¯ä¸ªæä»¶åªåä¸ä»¶äºæ 并导åºï¼è¿æ ·å¯è¯»æ§åå¯ç»´æ¤æ§æ´å¥½ã ```javascript // bad export function foo() {} // good export default function foo() {} ``` * 10.7 `import` æ¾å¨å ¶ä»ææè¯å¥ä¹åã eslint: [`import/first`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/first.md) > 鲿¢æå¤è¡ä¸ºã ```javascript // bad import foo from 'foo'; foo.init(); import bar from 'bar'; // good import foo from 'foo'; import bar from 'bar'; foo.init(); ``` * 10.8 å¤è¡ import åºè¯¥ç¼©è¿ï¼å°±åå¤è¡æ°ç»å对象åé¢é ```javascript // bad import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path'; // good import { longNameA, longNameB, longNameC, longNameD, longNameE, } from 'path'; ``` * 10.9 å¨ import è¯å¥éä¸å 许 Webpack loader è¯æ³ eslint: [`import/no-webpack-loader-syntax`](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-webpack-loader-syntax.md) > æå¥½æ¯å¨`webpack.config.js`éå ```javascript // bad import fooSass from 'css!sass!foo.scss'; import barCss from 'style!css!bar.css'; // good import fooSass from 'foo.scss'; import barCss from 'bar.css'; ``` ## è¿ä»£å¨åçæå¨ * 11.1 ä¸è¦ç¨è¿ä»£å¨ãç¨ JavaScript é«é¶å½æ°ä»£æ¿`for-in`ã `for-of`ã eslint: [`no-iterator`](http://eslint.org/docs/rules/no-iterator.html) [`no-restricted-syntax`](http://eslint.org/docs/rules/no-restricted-syntax) > ä¸å¯åååï¼å¤ççº¯å½æ°çè¿å弿¯å¤çå¯ä½ç¨æ´å®¹æã > æ°ç»çè¿ä»£æ¹æ³ï¼ `map()` / `every()` / `filter()` / `find()` / `findIndex()` / `reduce()` / `some()` / ... , 对象çå¤çæ¹æ³ ï¼`Object.keys()` / `Object.values()` / `Object.entries()` å»äº§çä¸ä¸ªæ°ç»ï¼ è¿æ ·ä½ å°±è½å»éå对象äºã ```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; // bad const increasedByOne = []; for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } // good const increasedByOne = []; numbers.forEach(num => increasedByOne.push(num + 1)); // best (keeping it functional) const increasedByOne = numbers.map(num => num + 1); ``` * 11.2 ç°å¨ä¸è¦ç¨ generator > å ¼å®¹æ§ä¸å¥½ * 11.3 å¦æä½ ä¸å®è¦ç¨ï¼æè ä½ å¿½ç¥[æä»¬ç建议](#generators--nope), 请确ä¿å®ä»¬ç彿°ç¾åä¹é´çç©ºæ ¼æ¯æ£ç¡®çã eslint: [`generator-star-spacing`](http://eslint.org/docs/rules/generator-star-spacing) > `function` å `*` æ¯å䏿¦å¿µï¼å ³é®å `*`䏿¯`function`ç修饰符ï¼`function*`æ¯ä¸ä¸ªå`function`ä¸ä¸æ ·çç¬ç¹ç»æ ```js // bad function * foo() { // ... } // bad const bar = function * () { // ... } // bad const baz = function *() { // ... } // bad const quux = function*() { // ... } // bad function*foo() { // ... } // bad function *foo() { // ... } // very bad function * foo() { // ... } // very bad const wat = function * () { // ... } // good function* foo() { // ... } // good const foo = function* () { // ... } ``` ## 屿§ * 12.1 访é®å±æ§æ¶ä½¿ç¨ç¹ç¬¦å·. eslint: [`dot-notation`](http://eslint.org/docs/rules/dot-notation.html) ```javascript const luke = { jedi: true, age: 28, }; // bad const isJedi = luke['jedi']; // good const isJedi = luke.jedi; ``` * 12.2 è·åç屿§æ¯åéæ¶ç¨æ¹æ¬å·`[]` ```javascript const luke = { jedi: true, age: 28, }; function getProp(prop) { return luke[prop]; } const isJedi = getProp('jedi'); ``` * 12.3 åå¹è¿ç®æ¶ç¨å¹æä½ç¬¦ `**` ã eslint: [`no-restricted-properties`](https://eslint.org/docs/rules/no-restricted-properties). ```javascript // bad const binary = Math.pow(2, 10); // good const binary = 2 ** 10; ``` ## åé * 13.1 å§ç»ç¨ `const` æ `let` 声æåéãå¦æä½ ä¸æ³éå°ä¸å¯¹åéæåãå ¨å±åéç bug çè¯ã eslint: [`no-undef`](http://eslint.org/docs/rules/no-undef) [`prefer-const`](http://eslint.org/docs/rules/prefer-const) ```javascript // bad superPower = new SuperPower(); // good const superPower = new SuperPower(); ``` * 13.2 æ¯ä¸ªåéåç¬ç¨ä¸ä¸ª `const` æ `let `ã eslint: [`one-var`](http://eslint.org/docs/rules/one-var.html) ```javascript // 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; ``` * 13.4 åéå£°ææ¾å¨åççä½ç½® ```javascript // bad - unnecessary function call function checkName(hasName) { const name = getName(); if (hasName === 'test') { return false; } if (name === 'test') { this.setName(''); return false; } return name; } // good function checkName(hasName) { if (hasName === 'test') { return false; } // å¨éè¦çæ¶ååé const name = getName(); if (name === 'test') { this.setName(''); return false; } return name; } ``` * 13.5 ä¸è¦ä½¿ç¨è¿ç»åéåé ã eslint: [`no-multi-assign`](https://eslint.org/docs/rules/no-multi-assign) > Why? 龿¥åéåé å建éå¼å ¨å±åéã ```javascript // 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` ä¹ä¸æ · ``` * 13.6 ä¸è¦ä½¿ç¨ä¸å éå¢éåè¿ç®ç¬¦ï¼`++`ï¼ `--`ï¼. eslint [`no-plusplus`](http://eslint.org/docs/rules/no-plusplus) > æ ¹æ® eslint ææ¡£ï¼ä¸å éå¢åéåè¯å¥åå°èªå¨åå·æå ¥çå½±åï¼å¹¶ä¸å¯è½ä¼å¯¼è´åºç¨ç¨åºä¸çå¼é墿éåçéé»é误ã 使ç¨num += 1 è䏿¯ num++ æä»£æ¿è¯å¥æ¥æ¹åä½ çå¼ä¹æ´å ·è¡¨ç°åãç¦æ¢ä¸å éå¢åéåè¯å¥ä¹ä¼é»æ¢æ¨æ æä¸é¢å éå¢/é¢éåå¼ï¼ä»èåå°ç¨åºåºç°æå¤è¡ä¸ºã ```javascript // 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; ``` * 13.7 é¿å å¨ `=` å/忢è¡ã å¦æä½ çè¯å¥è¶ åº [`max-len`](https://eslint.org/docs/rules/max-len.html)ï¼ é£å°±ç¨`()`æè¿ä¸ªå¼å èµ·æ¥åæ¢è¡ã eslint [`operator-linebreak`](https://eslint.org/docs/rules/operator-linebreak.html). ```javascript // bad const foo = superLongLongLongLongLongLongLongLongFunctionName(); // bad const foo = 'superLongLongLongLongLongLongLongLongString'; // good const foo = ( superLongLongLongLongLongLongLongLongFunctionName() ); // good const foo = 'superLongLongLongLongLongLongLongLongString'; ``` * 13.8 ä¸å è®¸ææªä½¿ç¨çåéã eslint: [`no-unused-vars`](https://eslint.org/docs/rules/no-unused-vars) ```javascript // bad var some_unused_var = 42; // å®ä¹äºæ²¡æä½¿ç¨ var y = 10; y = 5; // ä¸ä¼å°ç¨äºä¿®æ¹èªèº«ç读åè§ä¸ºå·²ä½¿ç¨ var z = 0; z = z + 1; // åæ°å®ä¹äºä½æªä½¿ç¨ 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' å³ä½¿æ²¡æä½¿ç¨ä¹å¯ä»¥è¢«å¿½ç¥ï¼ å 为è¿ä¸ªæä¸ä¸ª rest åå¼ç屿§ã // è¿æ¯ä»å¯¹è±¡ä¸æ½åä¸ä¸ªå¿½ç¥ç¹æ®å段ç对象çä¸ç§å½¢å¼ var { type, ...coords } = data; // 'coords' ç°å¨å°±æ¯ä¸ä¸ªæ²¡æ 'type' 屿§ç 'data' 对象 ``` ## æå * 14.1 var 声æè¢«æåãconst å let 声æè¢«èµäºä¸ä¸ªæè°çæ°æ¦å¿µ[Temporal Dead Zones (TDZ)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let)ã éè¦çæ¯è¦ç¥é为ä»ä¹ [typeofä¸åå®å ¨](http://es-discourse.com/t/why-typeof-is-no-longer-safe/15). ```javascript function example() { console.log(notDefined); // => throws a ReferenceError } // å¨åé声æä¹å使ç¨ä¼æ£å¸¸è¾åºï¼æ¯å 为åé声ææåï¼å¼æ²¡æã 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 å¿å彿°è¡¨è¾¾å¼å `var` æ åµç¸å ```javascript function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function () { console.log('anonymous function expression'); }; } ``` * 14.3 å·²å½åç彿°è¡¨è¾¾å¼æåä»çåéåï¼è䏿¯å½æ°åæå½æ°ä½ ```javascript function example() { console.log(named); // => undefined named(); // => TypeError named is not a function superPower(); // => ReferenceError superPower is not defined var named = function superPower() { console.log('Flying'); }; } // 彿°åååéåç¸å乿¯ä¸æ · function example() { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); }; } ``` * 14.4 彿°å£°æåæåäºå½æ°åå彿°ä½ ```javascript function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } } ``` * æ´å¤ä¿¡æ¯åå¾[JavaScript Scoping & Hoisting](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting/) by [Ben Cherry](http://www.adequatelygood.com/). ## æ¯è¾åç¸ç * 15.1 ä½¿ç¨ `===` å `!==` è䏿¯ `==` å `!=`. eslint: [`eqeqeq`](http://eslint.org/docs/rules/eqeqeq.html) * 15.2 `if` çæ¡ä»¶è¯å¥ä½¿ç¨å¼ºå¶ `ToBoolean` æ½è±¡æ¹æ³æ¥è¯ä¼°å®ä»¬ç表达å¼ï¼å¹¶ä¸å§ç»éµå¾ªä»¥ä¸ç®åè§åï¼ * **Objects** => **true** * **Undefined** => **false** * **Null** => **false** * **Booleans** => **the value of the boolean** * **Numbers** * **+0, -0, or NaN** => **false** * å ¶ä» => **true** * **Strings** * `''` => **false** * å ¶ä» => **true** ```javascript if ([0] && []) { // true // æ°ç»ï¼å³ä½¿æ¯ç©ºæ°ç»ï¼æ¯å¯¹è±¡ï¼å¯¹è±¡ä¼è®¡ç®æ true } ``` * 15.3 å¸å°å¼æ¯è¾å¯ä»¥çç¥ï¼ä½æ¯åç¬¦ä¸²åæ°åè¦æ¾ç¤ºæ¯è¾ ```javascript // bad if (isValid === true) { // ... } // good if (isValid) { // ... } // bad if (name) { // ... } // good if (name !== '') { // ... } // bad if (collection.length) { // ... } // good if (collection.length > 0) { // ... } ``` * 15.4 `switch case` ä¸ï¼å¨ `case` å `default` åå¥éç¨å¤§æ¬å·å建ä¸ä¸ªå(å¦ï¼`let`, `const`, `function`, and `class`). eslint rules: [`no-case-declarations`](http://eslint.org/docs/rules/no-case-declarations.html). > è¯æ±å£°æå¨æ´ä¸ª switch åä¸é½æ¯å¯è§çï¼ä½åªæå¨åé æ¶æä¼è¢«åå§åï¼è¿åªæå¨ case è¾¾å°æ¶æä¼åçãå½å¤ä¸ª case åå¥å°è¯å®ä¹ç¸åçäºç©æ¶ï¼ä¼åºç°é®é¢ã ```javascript // bad switch (foo) { case 1: let x = 1; break; case 2: const y = 2; break; case 3: function f() { // ... } break; default: class C {} } // good switch (foo) { case 1: { let x = 1; break; } case 2: { const y = 2; break; } case 3: { function f() { // ... } break; } case 4: bar(); break; default: { class C {} } } ``` * 15.5 ä¸å 表达å¼ä¸åºè¯¥åµå¥ï¼é常æ¯åè¡è¡¨è¾¾å¼ã eslint rules: [`no-nested-ternary`](http://eslint.org/docs/rules/no-nested-ternary.html). ```javascript // 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; ``` * 15.7 é¿å ä¸éè¦çä¸å è¡¨è¾¾å¼ eslint rules: [`no-unneeded-ternary`](http://eslint.org/docs/rules/no-unneeded-ternary.html). ```javascript // 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; ``` * 15.8 æ··åæä½ç¬¦æ¶ï¼è¦æ¾å¨ `()` éï¼åªæå½å®ä»¬æ¯æ åçç®æ¯è¿ç®ç¬¦(`+`, `-`, `*`, & `/`)ï¼ å¹¶ä¸å®ä»¬çä¼å 级æ¾èæè§æ¶ï¼å¯ä»¥ä¸ç¨ã eslint: [`no-mixed-operators`](https://eslint.org/docs/rules/no-mixed-operators.html) ```javascript // bad const foo = a && b < 0 || c > 0 || d + 1 === 0; // bad const bar = a ** b - 5 % d; // bad 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; ``` ## å * 16.1 ç¨å¤§æ¬å· `{}` å 裹å¤è¡ä»£ç åã eslint: [`nonblock-statement-body-position`](https://eslint.org/docs/rules/nonblock-statement-body-position) ```javascript // bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function foo() { return false; } // good function bar() { return false; } ``` * 16.2 `else` å `if` ç大æ¬å·ä¿æå¨ä¸è¡ã eslint: [`brace-style`](http://eslint.org/docs/rules/brace-style.html) ```javascript // bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); } ``` * 16.3 妿 `if` è¯å¥é½è¦ç¨ `return` è¿åï¼ é£åé¢ç `else` å°±ä¸ç¨åäºã 妿 `if` åä¸å å« `return`ï¼ å®åé¢ç `else if` åä¸ä¹å å«äº `return`ï¼ è¿ä¸ªæ¶åå°±å¯ä»¥æ `else if` æå¼ã eslint: [`no-else-return`](https://eslint.org/docs/rules/no-else-return) ```javascript // 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; } } ``` ## æ§å¶ * 17.1 å½ä½ çæ§å¶è¯å¥ `if`, `while` çå¤ªé¿æè è¶ è¿æå¤§é¿åº¦éå¶çæ¶åï¼ææ¯ä¸ªå¤ææ¡ä»¶æ¾å¨åç¬ä¸è¡éï¼é»è¾è¿ç®ç¬¦æ¾å¨è¡é¦ã ```javascript // 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(); } ``` * 17.2 ä¸è¦ç¨éæ©æä½ç¬¦ä»£æ¿æ§å¶è¯å¥ã ```javascript // bad !isRunning && startRunning(); // good if (!isRunning) { startRunning(); } ``` ## 注é * 18.1 å¤è¡æ³¨éç¨ `/** ... */` ```javascript // bad // make() returns a new element // based on the passed in tag name // // @param {String} tag // @return {Element} element function make(tag) { // ... return element; } // good /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; } ``` * 18.2 åè¡æ³¨éç¨`//`ï¼å°åè¡æ³¨éæ¾å¨è¢«æ³¨éåºå䏿¹ãå¦ææ³¨é䏿¯å¨ç¬¬ä¸è¡ï¼å°±å¨æ³¨éåé¢å ä¸ä¸ªç©ºè¡ ```javascript // 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; } // also good function getType() { // set the default type to 'no type' const type = this._type || 'no type'; return type; } ``` * 18.3 æææ³¨éå¼å¤´å ä¸ä¸ªç©ºæ ¼ï¼æ¹ä¾¿é 读ã eslint: [`spaced-comment`](http://eslint.org/docs/rules/spaced-comment) ```javascript // 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 */ function make(tag) { // ... return element; } // good /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; } ``` * 18.4 卿³¨éåå ä¸ `FIXME' æ `TODO` åç¼ï¼ è¿æå©äºå ¶ä»å¼å人åå¿«éçè§£ä½ æåºçé®é¢ï¼ æè æ¨å»ºè®®çé®é¢çè§£å³æ¹æ¡ã ```javascript class Calculator extends Abacus { constructor() { super(); // FIXME: shouldn't use a global here total = 0; } } ``` ```javascript class Calculator extends Abacus { constructor() { super(); // TODO: total should be configurable by an options param this.total = 0; } } ``` ## ç©ºæ ¼ * 19.1 Tab 使ç¨ä¸¤ä¸ªç©ºæ ¼ï¼æè 4 个ï¼ä½ å¼å¿å°±å¥½ï¼ä½æ¯å¢éç»ä¸æ¯å¿ é¡»çï¼ã eslint: [`indent`](http://eslint.org/docs/rules/indent.html) ```javascript // bad function foo() { ââââconst name; } // bad function bar() { âconst name; } // good function baz() { ââconst name; } ``` * 19.2 å¨å¤§æ¬å· `{}` åç©ºä¸æ ¼ã eslint: [`space-before-blocks`](http://eslint.org/docs/rules/space-before-blocks.html) ```javascript // bad function test(){ console.log('test'); } // good function test() { console.log('test'); } // bad dog.set('attr',{ age: '1 year', breed: 'Bernese Mountain Dog', }); // good dog.set('attr', { age: '1 year', breed: 'Bernese Mountain Dog', }); ``` * 19.3 卿§å¶è¯å¥ `if`, `while` çç忬å·åç©ºä¸æ ¼ãå¨å½æ°è°ç¨åå®ä¹æ¶ï¼å½æ°åå忬å·ä¹é´ä¸ç©ºæ ¼ã eslint: [`keyword-spacing`](http://eslint.org/docs/rules/keyword-spacing.html) ```javascript // bad if(isJedi) { fight (); } // good if (isJedi) { fight(); } // bad function fight () { console.log ('Swooosh!'); } // good function fight() { console.log('Swooosh!'); } ``` * 19.4 ç¨ç©ºæ ¼æ¥éå¼è¿ç®ç¬¦ã eslint: [`space-infix-ops`](http://eslint.org/docs/rules/space-infix-ops.html) ```javascript // bad const x=y+5; // good const x = y + 5; ``` * 19.5 æä»¶ç»å°¾ç©ºä¸è¡. eslint: [`eol-last`](https://github.com/eslint/eslint/blob/master/docs/rules/eol-last.md) ```javascript // bad import { es6 } from './AirbnbStyleGuide'; // ... export default es6; ``` ```javascript // bad import { es6 } from './AirbnbStyleGuide'; // ... export default es6;âµ âµ ``` ```javascript // good import { es6 } from './AirbnbStyleGuide'; // ... export default es6;âµ ``` * 19.6 å½åºç°é¿çæ¹æ³é¾ï¼ä¸è¬è¶ è¿ä¸¤ä¸ªçæ¶åï¼æ¶æ¢è¡ãç¨ç¹å¼å¤´å¼ºè°è¯¥è¡æ¯ä¸ä¸ªæ¹æ³è°ç¨ï¼è䏿¯ä¸ä¸ªæ°çè¯å¥ãeslint: [`newline-per-chained-call`](http://eslint.org/docs/rules/newline-per-chained-call) [`no-whitespace-before-property`](http://eslint.org/docs/rules/no-whitespace-before-property) ```javascript // bad $('#items').find('.selected').highlight().end().find('.open').updateCount(); // bad $('#items'). find('.selected'). highlight(). end(). find('.open'). updateCount(); // good $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount(); // bad 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); ``` * 19.7 å¨ä¸ä¸ªä»£ç åä¹åï¼ä¸ä¸æ¡è¯å¥ä¹å空ä¸è¡ã ```javascript // 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; ``` * 19.8 ä¸è¦æ æçä¸äºæ²¡å¿ è¦ç空ç½è¡ã eslint: [`padded-blocks`](http://eslint.org/docs/rules/padded-blocks.html) ```javascript // 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); } ``` * 19.9 忬å·éä¸è¦å ç©ºæ ¼ã eslint: [`space-in-parens`](http://eslint.org/docs/rules/space-in-parens.html) ```javascript // bad function bar( foo ) { return foo; } // good function bar(foo) { return foo; } // bad if ( foo ) { console.log(foo); } // good if (foo) { console.log(foo); } ``` * 19.10 æ¹æ¬å·éä¸è¦å ç©ºæ ¼ãç示ä¾ã eslint: [`array-bracket-spacing`](http://eslint.org/docs/rules/array-bracket-spacing.html) ```javascript // bad const foo = [ 1, 2, 3 ]; console.log(foo[ 0 ]); // goodï¼ éå·åé¢è¦å ç©ºæ ¼ const foo = [1, 2, 3]; console.log(foo[0]); ``` * 19.11 è±æ¬å· `{}` éå ç©ºæ ¼ã eslint: [`object-curly-spacing`](http://eslint.org/docs/rules/object-curly-spacing.html) ```javascript // bad const foo = {clark: 'kent'}; // good const foo = { clark: 'kent' }; // bad function foo() {return true;} if (foo) { bar = 0;} // good function foo() { return true; } if (foo) { bar = 0; } ``` * 19.12 é¿å ä¸è¡ä»£ç è¶ è¿ 100 个å符ï¼å å«ç©ºæ ¼ã纯å符串就ä¸è¦æ¢è¡äºï¼ã ```javascript // 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.')); ``` * 19.13 `,` åé¿å ç©ºæ ¼ï¼ `,` åéè¦ç©ºæ ¼ã eslint: [`comma-spacing`](https://eslint.org/docs/rules/comma-spacing) ```javascript // bad var foo = 1,bar = 2; var arr = [1 , 2]; // good var foo = 1, bar = 2; var arr = [1, 2]; ``` * 19.14 å¨å¯¹è±¡ç屿§ä¸ï¼ é®å¼ä¹é´è¦æç©ºæ ¼ã eslint: [`key-spacing`](https://eslint.org/docs/rules/key-spacing) ```javascript // bad var obj = { "foo" : 42 }; var obj2 = { "foo":42 }; // good var obj = { "foo": 42 }; ``` * 19.15 è¡æ«ä¸è¦ç©ºæ ¼ã eslint: [`no-trailing-spaces`](https://eslint.org/docs/rules/no-trailing-spaces) * 19.16 é¿å åºç°å¤ä¸ªç©ºè¡ã 卿件æ«å°¾åªå 许空ä¸è¡ã eslint: [`no-multiple-empty-lines`](https://eslint.org/docs/rules/no-multiple-empty-lines) ```javascript // bad var x = 1; var y = 2; // good var x = 1; var y = 2; ``` ## éå· * 20.1 ä¸è¦åç½®éå·ã eslint: [`comma-style`](http://eslint.org/docs/rules/comma-style.html) ```javascript // 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', }; ``` * 20.2 ç»å°¾é¢å¤å éå·ï¼çå¢éä¹ æ¯å§ eslint: [`comma-dangle`](http://eslint.org/docs/rules/comma-dangle.html) ```diff // bad - 没æç»å°¾éå·ç git diff const hero = { firstName: 'Florence', - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'] }; // good - æç»å°¾éå·ç git diff const hero = { firstName: 'Florence', lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'], }; ``` ```javascript // 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 ) ``` ## åå· * 21.1 å½ JavaScript éå°æ²¡æåå·çæ¢è¡ç¬¦æ¶ï¼å®ä¼ä½¿ç¨[`Automatic Semicolon Insertion`](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion)è¿ä¸è§åæ¥å³å®è¡æ«æ¯å¦å åå·ã使¯ï¼ASI å å«ä¸äºå¤æªçè¡ä¸ºï¼å¦æ JavaScript å¼éäºä½ çæ¢è¡ç¬¦ï¼ä½ ç代ç å°±ä¼ç ´åãæä»¥æç¡®å°ä½¿ç¨åå·ï¼ä¼åå°è¿ç§ä¸ç¡®å®æ§ã ```javascript // bad (function () { const name = 'Skywalker' return name })() // good (function () { const name = 'Skywalker'; return name; }()); // good ;(() => { const name = 'Skywalker'; return name; }()); ``` [æ´å¤](https://stackoverflow.com/questions/7365172/semicolon-before-self-invoking-function/7365214%237365214). ## ç±»å * 22.1 å¨å£°æå¼å¤´æ§è¡å¼ºå¶ç±»å转æ¢ã * 22.2 String eslint: [`no-new-wrappers`](https://eslint.org/docs/rules/no-new-wrappers) ```javascript // => 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); ``` * 22.3 Number eslint: [`radix`](http://eslint.org/docs/rules/radix) ```javascript 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); ``` * 22.4 è¯·å¨æ³¨éä¸è§£é为ä»ä¹è¦ç¨ç§»ä½è¿ç®ï¼æ è®ºä½ å¨åä»ä¹ï¼æ¯å¦ç±äº `parseInt` æ¯ä½ çæ§è½ç¶é¢å¯¼è´ä½ ä¸å®è¦ç¨ç§»ä½è¿ç®ã 请说æè¿ä¸ªæ¯å 为[æ§è½åå ](https://jsperf.com/coercion-vs-casting/3), ```javascript // good /** * parseInt 导è´ä»£ç è¿è¡æ ¢ * Bitshifting the String å°å ¶å¼ºå¶è½¬æ¢ä¸ºæ°åä½¿å ¶å¿«å¾å¤ã */ const val = inputValue >> 0; ``` * 22.5 **注æ:** ä½¿ç¨ bitshift æä½æ¶è¦å°å¿ãæ°å表示为 64 ä½å¼ï¼ä½ bitshift æä½å§ç»è¿å 32 使´æ°ã对äºå¤§äº32ä½çæ´æ°å¼ï¼Bitshiftå¯è½ä¼å¯¼è´æå¤è¡ä¸ºã ```javascript 2147483647 >> 0 //=> 2147483647 2147483648 >> 0 //=> -2147483648 2147483649 >> 0 //=> -2147483647 ``` * 22.6 Booleans ```javascript const age = 0; // bad const hasAge = new Boolean(age); // good const hasAge = Boolean(age); // best const hasAge = !!age; ``` ## å½åçº¦å® * 23.1 é¿å ç¨ä¸ä¸ªåæ¯å½åï¼è®©ä½ çå½åæ´å è¯ä¹åã eslint: [`id-length`](http://eslint.org/docs/rules/id-length) ```javascript // bad function q() { // ... } // good function query() { // ... } ``` * 23.2 ç¨ camelCase å½åä½ ç对象ã彿°ãå®ä¾ã eslint: [`camelcase`](http://eslint.org/docs/rules/camelcase.html) ```javascript // bad const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // good const thisIsMyObject = {}; function thisIsMyFunction() {} ``` * 23.3 ç¨ PascalCase å½åç±»ã eslint: [`new-cap`](http://eslint.org/docs/rules/new-cap.html) ```javascript // 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', }); ``` * 23.4 ä¸è¦ç¨åç½®æåç½®ä¸å线ã eslint: [`no-underscore-dangle`](http://eslint.org/docs/rules/no-underscore-dangle.html) > JavaScript 没æç§æå±æ§ææ¹æ³çæ¦å¿µã尽管åç½®ä¸å线éå¸¸çæ¦å¿µä¸æå³ç âprivateâï¼ä½å ¶å®ï¼è¿äºå±æ§æ¯å®å ¨å ¬å¼çï¼å æ¤è¿é¨å乿¯ä½ ç API çå 容ãè¿ä¸æ¦å¿µå¯è½ä¼å¯¼è´å¼åè è¯¯ä»¥ä¸ºæ´æ¹è¿ä¸ªä¸ä¼å¯¼è´å´©æºæè ä¸éè¦æµè¯ã ```javascript // bad this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; this._firstName = 'Panda'; // good this.firstName = 'Panda'; ``` * 23.5 ä¸è¦ä¿å `this` çå¼ç¨ï¼ä½¿ç¨ç®å¤´å½æ°æç¡¬ç»å®ã ```javascript // 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); }; } ``` * 23.6 æä»¶ååºä¸é»è®¤å¯¼åºï¼`export default`ï¼çåç§°å®å ¨å¹é ```javascript // 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 ``` * 23.7 é»è®¤å¯¼åºï¼`export default`ï¼ä¸ä¸ªå½æ°æ¶ï¼å½æ°åãæä»¶åç»ä¸ã ```javascript function makeStyleGuide() { // ... } export default makeStyleGuide; ``` * 23.8 å½ä½ export ä¸ä¸ªæé 彿°/ç±»/åä¾/彿°åºå¯¹è±¡æ¶ç¨ PascalCaseã ```javascript const AirbnbStyleGuide = { es6: { } }; export default AirbnbStyleGuide; ``` * 23.9 ç®ç§°åé¦åæ¯ç¼©ååºè¯¥å ¨é¨å¤§åæå ¨é¨å°åã > å忝ç»äººççï¼ä¸æ¯ç»çµèççã ```javascript // bad import SmsContainer from './containers/SmsContainer'; // bad const HttpRequests = [ // ... ]; // good import SMSContainer from './containers/SMSContainer'; // good const HTTPRequests = [ // ... ]; // best import TextMessageContainer from './containers/TextMessageContainer'; // best const Requests = [ // ... ]; ``` * 23.10 å ¨å¤§å忝å®ä¹ç¨æ¥å¯¼åºç常é ```javascript // bad const PRIVATE_VARIABLE = 'should not be unnecessarily uppercased within a file'; // bad export const THING_TO_BE_CHANGED = 'should obviously not be uppercased'; // bad export let REASSIGNABLE_VARIABLE = 'do not use let with uppercase variables'; // --- // allowed but does not supply semantic value export const apiKey = 'SOMEKEY'; // better in most cases export const API_KEY = 'SOMEKEY'; // --- // bad - unnecessarily uppercases key while adding no semantic value export const MAPPING = { KEY: 'value' }; // good export const MAPPING = { key: 'value' }; ``` ## 访é®å¨ * 24.1 ä¸éè¦ä½¿ç¨å±æ§ç访é®å¨å½æ°ã * 24.2 ä¸è¦ä½¿ç¨ JavaScript ç getters/settersï¼å 为ä»ä»¬ä¼äº§çå¯ä½ç¨ï¼å¹¶ä¸é¾ä»¥æµè¯ãç»´æ¤åçè§£ãå¦æå¿ è¦ï¼ä½ å¯ä»¥ç¨ getVal()å setVal() å»æå»ºã ```javascript // bad class Dragon { get age() { // ... } set age(value) { // ... } } // good class Dragon { getAge() { // ... } setAge(value) { // ... } } ``` * 24.3 妿屿§/æ¹æ³æ¯ä¸ä¸ª `boolean`ï¼ è¯·ç¨ `isVal()` æ `hasVal()`ã ```javascript // bad if (!dragon.age()) { return false; } // good if (!dragon.hasAge()) { return false; } ``` * 24.4 å¯ä»¥ç¨ get() å set() 彿°ï¼ä½æ¯è¦ä¿æä¸è´ã ```javascript class Jedi { constructor(options = {}) { const lightsaber = options.lightsaber || 'blue'; this.set('lightsaber', lightsaber); } set(key, val) { this[key] = val; } get(key) { return this[key]; } } ``` ## Events * 25.1 ç»äºä»¶æå ¶ä»ä¼ éæ°æ®æ¶ï¼ä¸ç´æ¥ä½¿ç¨åå§å¼ï¼èæ¯éè¿å¯¹è±¡å è£ ãè¿æ ·å¨æªæ¥éè¦å¢å æåå°åæ°ï¼ä¸å¿ æ¾å°æ¯ä¸ªä½¿ç¨ä¸çå¤çå¨ã ```javascript // bad $(this).trigger('listingUpdated', listing.id); ... $(this).on('listingUpdated', (e, listingId) => { // do something with listingId }); ``` prefer: ```javascript // good $(this).trigger('listingUpdated', { listingId: listing.id }); ... $(this).on('listingUpdated', (e, data) => { // do something with data.listingId }); ``` ## å°ç» æè°è§èï¼æ´å¤çè¿æ¯ä¸ºäºä»£ç çå¯è¯»æ§ï¼æ¯ç«æä»¬çä»£ç æ´éè¦çæ¯ç»äººçãåæ¶ï¼åççè§èï¼ä¹ä¼å¸®å©æä»¬è§é¿å¾å¤ä¸å¿ è¦ç bugã ## 交æµç¾¤ > å ³æ³¨å¾®ä¿¡å ¬ä¼å·ï¼å端å卿ºï¼åå¤ï¼å 群ã ## åè®° å¦æä½ çå°äºè¿éï¼ä¸æ¬æå¯¹ä½ æä¸ç¹å¸®å©çè¯ï¼å¸æä½ å¯ä»¥å¨å¨å°ææ¯æä¸ä¸ä½è ï¼æè°¢ð»ãæä¸å¦æä¸å¯¹ä¹å¤ï¼ä¹æ¬¢è¿å¤§å®¶æåºï¼å ±åã好äºï¼åè½è¯¯å¤§å®¶çæ¶é´äºï¼æè°¢é 读ï¼ä¸æ¬¡åè§ï¼ * **æç« ä»åº** [ð¹ð°fe-code](https://github.com/wuyawei/fe-code) * **[社交è天系ç»ï¼vue + node + mongodbï¼- ðð¦ðVchat](https://github.com/wuyawei/Vchat)** æå ´è¶£çåå¦å¯ä»¥å ³æ³¨ä¸æçå ¬ä¼å· **å端å卿º**ï¼å¥½ç©åææã 