基于Airbnb JavaScript Style Guide的javascript代码规范
本文是完整代码规范建议的子集,提及内容为eslint
可检查部分。
补充规范:
IDE/构建工具/格式化工具配置请看配置文档
本文规则分为三类:
- 强制: 不符合规范 =>
eslint error
- 建议 / warn: 不符合规范 =>
eslint warn
警告提示 - 建议 / off: 建议你以这样的方式进行 =>
eslint off
不进行检查
建议通读完整规范,获得更好的代码书写指导建议。
修改的部分会以[modified]
标注,无此说明的即与原文规约相同。
- 对象
- 数组
- 解构
- 字符串
- 函数
- 箭头函数
- 构造函数
- 模块
- Iterators & Generators
- 属性
- 变量
- 提升
- 比较运算符 & 等号
- 代码块
- 注释
- 空白
- 逗号
- 分号
- 类型转换
- 命名规则
- 存取器
- 事件
- jQuery
- ECMAScript 5 兼容性
- ECMAScript 6 编码规范
-
2.1 [强制] 对所有的引用使用
const
;不要使用var
。 eslint:prefer-const
,no-const-assign
为什么?这能确保你无法对引用重新赋值,也不会导致出现 bug 或难以理解。
// bad var a = 1; var b = 2; // good const a = 1; const b = 2;
-
2.2 [强制] 如果你一定需要可变动的引用,使用
let
代替var
。 eslint:no-var
jscs:disallowVar
为什么?因为
let
是块级作用域,而var
是函数作用域。// bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; }
-
3.1 [强制] 使用字面值创建对象。 eslint:
no-new-object
// bad const item = new Object(); // good const item = {};
-
3.4 [强制] 使用对象属性值的简写。 eslint:
object-shorthand
jscs:requireEnhancedObjectLiterals
为什么?因为这样更短更有描述性。
const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, };
-
3.6 [强制] 仅在对象属性有特殊符号时使用引号包裹。 eslint:
quote-props
jscs:disallowQuotedKeysInObjects
为什么? 这样看上去更加易读,另外还能有相关的代码高亮,也容易被许多JS引擎优化。
// bad const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // good const good = { foo: 3, bar: 4, 'data-blah': 5, };
-
4.1 [强制] 使用字面值创建数组。 eslint:
no-array-constructor
// bad const items = new Array(); // good const items = [];
-
4.5 [强制] 数组的相关方法使用return语句。如果函数体仅由一个带表达式且无副作用的语句组成,可以忽略return。 参考8.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 const flat = {}; [[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => { const flatten = memo.concat(item); flat[index] = flatten; }); // good const flat = {}; [[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => { const flatten = memo.concat(item); flat[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; });
-
6.1 [强制] 字符串使用单引号
''
。 eslint:quotes
jscs:validateQuoteMarks
// bad const name = "Capt. Janeway"; // good const name = 'Capt. Janeway';
-
6.4
[modified]
[建议 / warn]程序化生成字符串时,使用模板字符串代替字符串连接。 eslint:prefer-template
template-curly-spacing
jscs:requireTemplateStrings
为什么?模板字符串更为简洁,更具可读性。
// bad function sayHi(name) { return 'How are you, ' + name + '?'; } // bad function sayHi(name) { return ['How are you, ', name, '?'].join(); } // good function sayHi(name) { return `How are you, ${name}?`; }
-
6.5
[modified]
[建议 / off] 不要对字符串使用不必要的escape操作。 eslint:no-useless-escape
为什么? 反斜杠会影响可读性,仅在必须的时候使用它。
// bad const foo = '\'this\' \i\s \"quoted\"'; // good const foo = '\'this\' is "quoted"'; const foo = `my name is '${name}'`;
-
7.1
[modified]
[建议 / off] 使用具名函数代替函数声明。 eslint:func-style
jscs:disallowFunctionDeclarations
为什么?因为函数声明会把函数提升(hoisted), 这样易使函数在定义前被引用。这会影响可读性和可维护性。如果一个函数的定义很长或很复杂,会干扰对文件剩余部分的理解,更好的方式是将它抽象在它自己的模块中。别忘了给函数表达式命名 - 匿名函数会使得在错误调用栈中定位问题变得困难。(讨论)
// bad function foo() { // ... } // bad const foo = function () { // ... }; // good const foo = function bar() { // ... };
-
7.2 [强制] 对于立即调用(IIFE)的函数表达式,用括号包裹函数体。 eslint:
wrap-iife
jscs:requireParenthesesAroundIIFE
为什么?立即调用函数是一个独立单元 - 用括号包裹函数体可以清晰地表达这一点。需要注意的是,在一个到处都是「模块」的世界,几乎从不需要IIFE。
// 立即调用的函数 (IIFE) (function () { console.log('Welcome to the Internet. Please follow me.'); }());
-
7.3 [强制] 永远不要在一个非函数代码块(
if
、while
等)中声明一个函数,把那个函数赋给一个变量。浏览器允许你这么做,但它们的解析表现不一致。 eslint:no-loop-func
-
7.6
[modified]
[建议 / off] 不要使用arguments
。可以选择 rest 语法...
替代。 eslint:prefer-rest-params
为什么?使用
...
能明确你要传入的参数。另外 rest 参数是一个真正的数组,而arguments
是一个类数组。// bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function concatenateAll(...args) { return args.join(''); }
-
7.10 [强制] 永远不要使用Function构造函数来创建一个新函数。 eslint:
no-new-func
为什么?这种方式在分析字符串时与eval()类似,会带来各种问题。
// 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
space-before-blocks
为什么?保持一致性是最佳实践, 另外如果在添加或删除名称时也不应增加/删除空格。
// bad const f = function(){}; const g = function (){}; const h = function() {}; // good const x = function () {}; const y = function a() {};
-
7.12 [强制] 永远不要改变(mutate)参数。 eslint:
no-param-reassign
为什么?对传入的参数进行操作会在原始调用带来不想要的变量副作用。
// bad function f1(obj) { obj.key = 1; } // good function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; }
-
7.13 [强制] 永远不要对参数重新赋值(reassign)。 eslint:
no-param-reassign
为什么?对参数重新赋值会引起意料之外的行为,特别是对于
arguments
的访问。同时它会引起优化问题,特别在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) { // ... }
-
7.14
[modified]
[建议 / warn] 推荐使用展开运算符...
来调用可变参数的函数。 eslint:prefer-spread
为什么?这样更加清晰,也不用提供上下文,而且把
new
和apply
组合的方式也比较蛋疼。// 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]);
-
8.1 [强制] 当你必须使用函数表达式(或传递一个匿名函数)时,使用箭头函数符号。 eslint:
prefer-arrow-callback
,arrow-spacing
jscs:requireArrowFunctions
为什么?因为箭头函数创造了新的一个
this
执行环境(译注:参考 Arrow functions - JavaScript | MDN 和 ES6 arrow functions, syntax and lexical scoping),通常情况下都能满足你的需求,而且这样的写法更为简洁。为什么不?如果你有一个相当复杂的函数,你或许可以把逻辑部分转移到一个函数声明上。
// 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 [强制] 如果一个函数适合用一行写出并且只有一个参数,那就把花括号、圆括号和
return
都省略掉。如果不是,那就不要省略。 eslint:arrow-parens
,arrow-body-style
jscs:disallowParenthesesAroundArrowParam
,requireShorthandArrowFunctions
为什么?语法糖。在链式调用中可读性很高。
// 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, })); // 当有副作用时,不要隐式return 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.4 [强制] 如果函数是单参数且不需要花括号
{}
,则要省略掉括号。否则,始终用括号包裹参数,这样更加清晰,可读性也更好。 注:始终使用括号包裹参数也可以。 在eslint中使用 “always” option 或在jscs中不引入disallowParenthesesAroundArrowParam
。 eslint:arrow-parens
jscs:disallowParenthesesAroundArrowParam
为什么? 可以避免视觉上的混乱。
// 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
[modified]
[建议 / off] 在箭头函数后避免使用 (<=
,>=
)这样的比较操作符。 eslint:no-confusing-arrow
// 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; };
-
9.1 [强制] 总是使用
class
。避免直接操作prototype
。为什么? 因为
class
语法更为简洁易读。// bad function Queue(contents = []) { this._queue = [...contents]; } Queue.prototype.pop = function() { const value = this._queue[0]; this._queue.splice(0, 1); return value; } // good class Queue { constructor(contents = []) { this._queue = [...contents]; } pop() { const value = this._queue[0]; this._queue.splice(0, 1); return value; } }
-
9.5 [强制]如果没有显式声明,类都有个默认的构造器(constructor)。一个空或者仅代理了父类的构造函数是不必要的。 eslint:
no-useless-constructor
// 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
为什么? 重复声明类成员,默认最后一个优先级最高 - 几乎肯定是个bug。
// bad class Foo { bar() { return 1; } bar() { return 2; } } // good class Foo { bar() { return 1; } } // good class Foo { bar() { return 2; } }
-
10.4 [强制] 避免从同一个位置重复import. eslint:
no-duplicate-imports
为什么? 这样会降低可维护性。
// 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 [强制] 不要将可变量export。 eslint:
import/no-mutable-exports
为什么? 一般来说需要避免可变,特别是在export可变量时。虽然在某些特殊情况下需要这么做,但是一般来说只对常量的引用作export。
// bad let foo = 3; export { foo }; // good const foo = 3; export { foo };
-
10.6 [强制] 只有单个export的模块,推荐使用default export而不是具名export。 eslint:
import/prefer-default-export
// bad export function foo() {} // good export default function foo() {}
-
10.7 [强制] 把所有的
import
放在非import句式前。 eslint:import/first
为什么?
import
存在提升(hoisted),把它们都置于文件顶部可以避免一些奇怪的行为。// bad import foo from 'foo'; foo.init(); import bar from 'bar'; // good import foo from 'foo'; import bar from 'bar'; foo.init();
-
10.9 [强制] 在import语句中不允许使用webpack loader语法。 eslint:
import/no-webpack-loader-syntax
为什么? 使用这种语法的代码对打包工具有强依赖。推荐在
webpack.config.js
中使用这类语法。// 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.3 [强制] 如果必须要使用generator, 那么要确保函数签名中使用正确的空格格式。 eslint:
generator-star-spacing
为什么?
function
和*
都是概念上的关键字 -*
不是function
的修饰符,function*
是一个统一结构体, 与function
不同。// 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 [建议 / warn] 使用
.
来访问对象的属性。 eslint:dot-notation
jscs:requireDotNotation
const luke = { jedi: true, age: 28, }; // bad const isJedi = luke['jedi']; // good const isJedi = luke.jedi;
-
13.1 [强制] 一直使用
const
或let
来声明变量,如果不这样做就会产生全局变量。 我们需要避免全局命名空间的污染。地球队长已经警告过我们了。(译注:全局,global 亦有全球的意思。地球队长的责任是保卫地球环境,所以他警告我们不要造成「全球」污染。)eslint:no-undef
prefer-const
// bad superPower = new SuperPower(); // good const superPower = new SuperPower();
-
13.2 [强制] 使用
const
或let
声明每一个变量。 eslint:one-var
jscs:disallowMultipleVarDecl
为什么?增加新变量将变的更加容易,而且你永远不用再担心调换错
;
跟,
。// 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.5 [强制] 不要使用链式变量赋值.
为什么?链式变量赋值会创建隐式全局变量。
// bad (function example() { // JavaScript 解释器将这个语句解释为 // let a = ( b = ( c = 1 ) ); // let关键字仅对a生效,b和c变成了全局变量。 let a = b = c = 1; }()); console.log(a); // throws ReferenceError console.log(b); // 1 console.log(c); // 1 // good (function example() { let a = 1; let b = a; let c = a; }()); console.log(a); // throws ReferenceError console.log(b); // throws ReferenceError console.log(c); // throws ReferenceError // 对于 `const`也是一样的。
-
13.6
[modified]
[建议 / off] 避免使用一元增减运算符(++, --)。 eslintno-plusplus
为什么? 根据eslint文档, 一元增减运算符会自动加入分号,在应用中会引起静默错误。使用
num += 1
代替num++
或num ++
来变更值会显得更加易读。 不使用一元增减运算符也可以避免在不注意的情况下值做了预增减(pre-incrementing/pre-decrementing),也会导致预期外的错误。// 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;
- 想了解更多信息,参考 Ben Cherry 的 JavaScript Scoping & Hoisting。
-
16.2 [强制] 如果通过
if
和else
使用多行代码块,把else
另起一行。把eslint:else
放在if
代码块关闭括号的同一行。brace-style
jscs:disallowNewlineBeforeBlockStatements
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
-
18.3 [强制] 所有注释开头加一个空格,增加可读性。 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 */ function make(tag) { // ... return element; } // good /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; }
-
19.1 [强制] 使用 2 个空格作为缩进。 eslint:
indent
jscs:validateIndentation
// bad function() { ∙∙∙∙const name; } // bad function() { ∙const name; } // good function() { ∙∙const name; }
-
19.2 [强制] 在花括号前放一个空格。 eslint:
space-before-blocks
jscs:requireSpaceBeforeBlockStatements
// 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
jscs:requireSpaceAfterKeywords
// 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
jscs:requireSpaceBeforeBinaryOperators
,requireSpaceAfterBinaryOperators
// bad const x=y+5; // good const x = y + 5;
-
19.5 [强制] 在文件末尾插入一个空行。 eslint:
eol-last
// bad (function(global) { // ...stuff... })(this);
// bad (function(global) { // ...stuff... })(this);↵ ↵
// good (function(global) { // ...stuff... })(this);↵
-
19.6 [强制] 在使用长方法链时进行缩进。使用前面的点
.
强调这是方法调用而不是新语句。 eslint:newline-per-chained-call
no-whitespace-before-property
译注:当链式超过4个之后使用换行。
// 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);
-
19.8 [强制]不要用代码块起始/结束位置加入空行。 eslint:
padded-blocks
jscs:disallowPaddingNewlinesInBlocks
// 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
jscs:disallowSpacesInsideParentheses
// 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
jscs:disallowSpacesInsideArrayBrackets
// 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
jscs:requireSpacesInsideObjectBrackets
// bad const foo = {clark: 'kent'}; // good const foo = { clark: 'kent' };
-
19.12 [强制] 避免一行超过100个字符。 备注:每个如上above的长字符串 可以不遵循这条规则。 eslint:
max-len
jscs:maximumLineLength
为什么?这样做可以增加可读性和可维护性。
// 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.'));
-
20.1 [强制] 行首逗号:不需要。 eslint:
comma-style
jscs:requireCommaBeforeLineBreak
// 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
jscs:requireTrailingComma
为什么? 这会让 git diffs 更干净。另外,像 babel 这样的转译器会移除结尾多余的逗号,也就是说你不必担心老旧浏览器的尾逗号问题。
// 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', ];
-
21.1 [强制] 在语句末使用分号 eslint:
semi
jscs:requireSemicolons
// bad (function() { const name = 'Skywalker' return name })() // good (() => { const name = 'Skywalker'; return name; })(); // good (防止函数在两个 IIFE 合并时被当成一个参数) ;(() => { const name = 'Skywalker'; return name; })();
-
22.3 [强制] 对数字使用
parseInt
转换,并带上类型转换的基数。 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);
-
23.1
[modified]
[建议 / off]避免单字母命名。命名应语义化。 eslint:id-length
// bad function q() { // ...stuff... } // good function query() { // ..stuff.. }
-
23.2 [强制] 使用驼峰式命名对象、函数和实例。 eslint:
camelcase
jscs:requireCamelCaseOrUpperCaseIdentifiers
// bad const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // good const thisIsMyObject = {}; function thisIsMyFunction() {}
-
23.3 [强制] 使用帕斯卡式命名构造函数或类。 eslint:
new-cap
jscs:requireCapitalizedConstructors
// 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
[modified]
[建议 / warn] 不要使用下划线_
结尾或开头来命名属性和方法。 eslint:no-underscore-dangle
jscs:disallowDanglingUnderscores
为什么? Javascript对属性或方法而言并没有「私有」的定义。虽然用大多人用下划线开头表示“私有”, 但是实际上这些方法是完全公有的,是公共API的一部分。这种方式会让开发者误认为修改不会影响到它,或者不需要测试。如果你需要一些“私有”定义,那么它们不应该这样显眼。
// bad this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; this._firstName = 'Panda'; // good this.firstName = 'Panda';
-
23.5 [强制] 别保存
this
的引用。使用箭头函数或 Function#bind. jscs:disallowNodeTypes
// 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); }; }
-
28.1 以下是链接到 ES6 的各个特性的列表。