Airbnb的JavaScript风格指南是目前业界认可度最高,使用最为广泛的JavaScript编写指南,很多公司也会结合此文档和实际情况编写内部的JS使用指南。
可以说这个指南代表了一种使用JavaScript最合理的方法。
本文对原文的中文简版进行了翻译上的优化和一些精简,可以方便开发人员快速使用。
注意: 本文中所有代码都是基于ES6的。
Types
types–primitives
当你访问一个基本类型时,你可以直接访问到它的值。
string
number
boolean
null
undefined
symbol
|
|
Symbols目前还没有完全匹配功能的polyfill(哪位大神开发下?),所以不应该在不能原生支持symbol类型的环境[浏览器]中使用 symbol 类型。
types–complex
当你访问一个复杂类型时,你访问的是它的引用(类似于C中指针的概念)。
object
array
function
|
|
References
避免使用var
。
references–prefer-const
优先使用const
声明变量
原因: 使用const
可以让你避免重复赋值,也可以认清哪些真正是“变”量。
eslint:
prefer-const
,no-const-assign
|
|
references–disallow-var
如果你有对参数重新赋值的需求,那就用let
吧。
原因: 因为let
是块级作用域,而var
是函数级作用域。let
完胜。
eslint:
no-var
|
|
references–block-scope
let
、const
都是块级作用域
|
|
Objects
objects–no-new
使用字面值({})创建对象.
eslint:
no-new-object
|
|
es6-computed-properties
当创建一个包含动态属性名的对象时,用下面的方式:
原因: 这可以使你的对象定义看起来更整洁,找属性的时候也方便。
|
|
es6-object-shorthand
用对象方法的简写方式.
eslint:
object-shorthand
|
|
es6-object-concise
用属性值缩写.
原因: 这样写的更少且更可读
eslint:
object-shorthand
|
|
objects–grouped-shorthand
将所有缩写的属性放在对象声明的开始.
原因: 这样也是为了更方便的知道有哪些属性用了缩写.
|
|
objects–quoted-props
只对必须要使用引号的属性使用引号 ''
.
原因: 通常我们认为这种方式主观上易读。他优化了代码,并且更容易压缩。
eslint:
quote-props
|
|
objects–prototype-builtins
不要直接调用Object.prototype
上的方法,如hasOwnProperty
, propertyIsEnumerable
, isPrototypeOf
。
原因::主要是怕一些对象的默认方法被更改或屏蔽过。如:{ hasOwnProperty: false }
- 或这是一个空对象Object.create(null)
|
|
objects–rest-spread
对象浅拷贝时,更推荐使用扩展运算符[就是...
运算符],而不是Object.assign
。获取对象指定的几个属性时,用对象的rest解构运算符[也是...
运算符]更好。
|
|
Arrays
arrays–literals
用字面量赋值。
eslint:
no-array-constructor
|
|
arrays–push
用Array#push 代替直接向数组中添加一个值。
|
|
es6-array-spreads
用扩展运算符做数组浅拷贝,类似上面的对象浅拷贝
|
|
arrays–from-iterable
用 ...
运算符而不是Array.from
来将一个可迭代的对象转换成数组。
|
|
arrays–from-array-like
用 Array.from
去将一个类数组对象转成一个数组。
|
|
arrays–mapping
用 Array.from
而不是 ...
运算符去做map遍历。 因为这样可以避免创建一个临时数组。
|
|
arrays–callback-return
在数组方法的回调函数中使用 return 语句。 如果函数体由一条返回一个表达式的语句组成, 并且这个表达式没有副作用, 这个时候可以忽略return,详见 8.2.
eslint:
array-callback-return
|
|
arrays–bracket-newline
如果一个数组有很多行,在数组的 [
后和 ]
前断行。 请看下面示例
|
|
Destructuring
destructuring–object
用对象的解构赋值来获取和使用对象某个或多个属性值。
eslint:
prefer-destructuring
原因 :解构保存了这些属性的临时值/引用
|
|
destructuring–array
用数组解构.
|
|
destructuring–object-over-array
多个返回值用对象的解构,而不是数据解构。
原因:你可以在后期添加新的属性或者变换变量的顺序而不会打破原有的调用
|
|
Strings
strings–quotes
对string用单引号 ''
。
eslint:
quotes
|
|
strings–line-length
超过100个字符的字符串不应该用string串联成多行。
原因:折断的字符串很容易出错,而且使得代码可读性和搜索性变差。
|
|
es6-template-literals
用字符串模板而不是字符串拼接来组织可编程字符串。
原因:模板字符串更具可读性、语法简洁、字符串插入参数。
|
|
strings–eval
永远不要在字符串中用eval()
,他就是潘多拉盒子。
eslint:
no-eval
strings–escaping
不要使用不必要的转义字符。
eslint:
no-useless-escape
原因:反斜线可读性差,所以他们只在必须使用时才出现哦
|
|
Functions
functions–declarations
用命名函数表达式而不是函数声明。
eslint:
func-style
函数表达式: const func = function () {}
函数声明: function func() {}
Why? 函数声明时作用域被提前了,这意味着在一个文件里函数很容易(太容易了)在其定义之前被引用。这样伤害了代码可读性和可维护性。如果你发现一个函数有大又复杂,这个函数妨碍这个文件其他部分的理解性,这可能就是时候把这个函数单独抽成一个模块了。别忘了给表达式显示的命名,不用管这个名字是不是由一个确定的变量推断出来的,这消除了由匿名函数在错误调用栈产生的所有假设,这在现代浏览器和类似babel编译器中很常见 (Discussion)
Why? 这一段还不理解这种错误发生的场景,所以只能直译过来了, 另附原文
Why? Function declarations are hoisted, which means that it’s easy - too easy - to reference the function before it is defined in the file. This harms readability and maintainability. If you find that a function’s definition is large or complex enough that it is interfering with understanding the rest of the file, then perhaps it’s time to extract it to its own module! Don’t forget to explicitly name the expression, regardless of whether or not the name is inferred from the containing variable (which is often the case in modern browsers or when using compilers such as Babel). This eliminates any assumptions made about the Error’s call stack. (Discussion)
|
|
functions–iife
把立即执行函数包裹在圆括号里。
eslint:
wrap-iife
Why? immediately invoked function expression = IIFE
Why? 一个立即调用的函数表达式是一个单元 - 把它和他的调用者(圆括号)包裹起来,在括号中可以清晰的地表达这些。
Why? 注意:在模块化世界里,你几乎用不着 IIFE
|
|
functions–in-blocks
不要在非函数块(if、while等等)内声明函数。把这个函数分配给一个变量。浏览器会允许你这样做,但浏览器解析方式不同,这是一个坏消息。【详见no-loop-func
】
eslint:
no-loop-func
functions–note-on-blocks
Note: 在ECMA-262中 [块 block
] 的定义是: 一系列的语句; 但是函数声明不是一个语句。 函数表达式是一个语句。
|
|
###functions–arguments-shadow
不要用arguments
命名参数。他的优先级高于每个函数作用域自带的 arguments
对象, 这会导致函数自带的 arguments
值被覆盖
|
|
es6-rest
不要使用arguments
,用rest语法...
代替。
eslint:
prefer-rest-params
Why?
...
明确你想用那个参数。而且rest参数是真数组,而不是类似数组的arguments
|
|
es6-default-parameters
用默认参数语法而不是在函数里对参数重新赋值。
|
|
functions–default-side-effects
默认参数避免副作用
Why? 他会令人迷惑不解, 比如下面这个, a到底等于几, 这个需要想一下。
|
|
functions–defaults-last
把默认参数赋值放在最后
|
|
functions–constructor
不要用函数构造器创建函数。 eslint: no-new-func
Why? 以这种方式创建函数将类似于字符串 eval(),这会打开漏洞。
|
|
functions–signature-spacing
函数签名部分要有空格。eslint: space-before-function-paren
space-before-blocks
Why? 统一性好,而且在你添加/删除一个名字的时候不需要添加/删除空格
|
|
functions–mutate-params
不要改参数. eslint: no-param-reassign
Why? 操作参数对象对原始调用者会导致意想不到的副作用。 就是不要改参数的数据结构,保留参数原始值和数据结构。
|
|
functions–reassign-params
不要对参数重新赋值。 eslint: no-param-reassign
Why? 参数重新赋值会导致意外行为,尤其是对
arguments
。这也会导致优化问题,特别是在V8里
|
|
functions–spread-vs-apply
用spread
操作符...
去调用多变的函数更好。 eslint: prefer-spread
Why? 这样更清晰,你不必提供上下文,而且你不能轻易地用
apply
来组成new
|
|
functions–signature-invocation-indentation
调用或者书写一个包含多个参数的函数应该想这个指南里的其他多行代码写法一样: 每行值包含一个参数,每行逗号结尾。
|
|
Arrow Functions
arrows–use-them
当你一定要用函数表达式(在回调函数里)的时候就用箭头表达式吧。 eslint: prefer-arrow-callback
, arrow-spacing
Why? 他创建了一个
this
的当前执行上下文的函数的版本,这通常就是你想要的;而且箭头函数是更简洁的语法Why? 什么时候不用箭头函数: 如果你有一个相当复杂的函数,你可能会把这个逻辑移出到他自己的函数声明里。
|
|
arrows–implicit-return
如果函数体由一个没有副作用的表达式语句组成,删除大括号和return。否则,继续用大括号和 return
语句。 eslint: arrow-parens
, arrow-body-style
Why? 语法糖,当多个函数链在一起的时候好读
|
|
arrows–paren-wrap
万一表达式涉及多行,把他包裹在圆括号里更可读。
Why? 这样清晰的显示函数的开始和结束
|
|
arrows–one-arg-parens
如果你的函数只有一个参数并且函数体没有大括号,就删除圆括号。否则,参数总是放在圆括号里。 注意: 一直用圆括号也是没问题,只需要配置 “always” option for eslint. eslint: arrow-parens
Why? 这样少一些混乱, 其实没啥语法上的讲究,就保持一个风格。
|
|
arrows–confusing
避免箭头函数(=>
)和比较操作符(<=, >=
)混淆. eslint: no-confusing-arrow
|
|
whitespace–implicit-arrow-linebreak
在隐式return中强制约束函数体的位置, 就写在箭头后面。 eslint: implicit-arrow-linebreak
|
|
Classes & Constructors
constructors–use-class
常用class
,避免直接操作prototype
Why?
class
语法更简洁更易理解
|
|
constructors–extends
用extends
实现继承
Why? 它是一种内置的方法来继承原型功能而不打破
instanceof
|
|
constructors–chaining
方法可以返回this
来实现方法链
|
|
constructors–tostring
写一个定制的toString()方法是可以的,只要保证它是可以正常工作且没有副作用的
|
|
constructors–no-useless
如果没有具体说明,类有默认的构造方法。一个空的构造函数或只是代表父类的构造函数是不需要写的。 eslint: no-useless-constructor
|
|
classes–no-duplicate-members
避免重复类成员。 eslint: no-dupe-class-members
Why? 重复类成员会默默的执行最后一个 —— 重复本身也是一个bug
|
|
Modules
modules–use-them
用(import
/export
) 模块而不是无标准的模块系统。你可以随时转到你喜欢的模块系统。
Why? 模块化是未来,让我们现在就开启未来吧。
|
|
modules–no-wildcard
不要用import通配符, 就是 *
这种方式
Why? 这确保你有单个默认的导出
|
|
modules–no-export-from-import
不要直接从import中直接export
Why? 虽然一行是简洁的,有一个明确的方式进口和一个明确的出口方式来保证一致性。
|
|
modules–no-duplicate-imports
一个路径只 import 一次。
eslint: no-duplicate-imports
Why? 从同一个路径下import多行会使代码难以维护
|
|
modules–no-mutable-exports
不要到处可变的东西
eslint: import/no-mutable-exports
Why? 变化通常都是需要避免,特别是当你要输出可变的绑定。虽然在某些场景下可能需要这种技术,但总的来说应该导出常量。
|
|
modules–prefer-default-export
在一个单一导出模块里,用 export default
更好。
eslint: import/prefer-default-export
Why? 鼓励使用更多文件,每个文件只做一件事情并导出,这样可读性和可维护性更好。
|
|
modules–imports-first
import
放在其他所有语句之前。
eslint: import/first
Why? 让
import
放在最前面防止意外行为。
|
|
modules–multiline-imports-over-newlines
多行import应该缩进,就像多行数组和对象字面量
Why? 花括号与样式指南中每个其他花括号块遵循相同的缩进规则,逗号也是。
|
|
modules–no-webpack-loader-syntax
在import语句里不允许Webpack loader语法
eslint: import/no-webpack-loader-syntax
Why? 一旦用Webpack语法在import里会把代码耦合到模块绑定器。最好是在
webpack.config.js
里写webpack loader语法
|
|
Iterators and Generators
iterators–nope
不要用遍历器。用JavaScript高级函数代替for-in
、 for-of
。 eslint: no-iterator
no-restricted-syntax
Why? 这强调了我们不可变的规则。 处理返回值的纯函数比副作用更容易。
Why? 用数组的这些迭代方法:
map()
/every()
/filter()
/find()
/findIndex()
/reduce()
/some()
/ … , 用对象的这些方法Object.keys()
/Object.values()
/Object.entries()
去产生一个数组, 这样你就能去遍历对象了。
|
|
generators–nope
现在不要用generator
Why? 它在es5上支持的不好
generators–spacing
如果你一定要用,或者你忽略我们的建议, 请确保它们的函数签名空格是得当的。 eslint: generator-star-spacing
Why?
function
和*
是同一概念关键字 -*
不是function
的修饰符,function*
是一个和function
不一样的独特结构
|
|
Properties
properties–dot
访问属性时使用点符号. eslint: dot-notation
|
|
properties–bracket
当获取的属性是变量时用方括号[]
取
|
|
es2016-properties–exponentiation-operator
做幂运算时用幂操作符 **
。 eslint: no-restricted-properties
.
|
|
Variables
variables–const
用const
声明变量。不这样做会导致全局变量。 我们想要避免污染全局命名空间。首长这样警告我们。 eslint: no-undef
prefer-const
|
|
variables–one-const
每个变量都用一个 const
或 let
。 eslint: one-var
Why? 这种方式很容易去声明新的变量,你不用去考虑把
;
调换成,
,或者引入一个只有标点的不同的变化。这种做法也可以是你在调试的时候单步每个声明语句,而不是一下跳过所有声明。
|
|
variables–const-let-group
const
放一起,let
放一起
Why? 在你需要分配一个新的变量, 而这个变量依赖之前分配过的变量的时候,这种做法是有帮助的
|
|
variables–define-where-used
在你需要的地方声明变量,但是要放在合理的位置
Why?
let
和const
都是块级作用域而不是函数级作用域
|
|
variables–no-chain-assignment
不要使用链接变量分配。 eslint: no-multi-assign
Why? 链接变量分配创建隐式全局变量。
|
|
variables–unary-increment-decrement
不要使用一元自增自减运算符(++
, --
). eslint no-plusplus
Why? 根据eslint文档,一元增量和减量语句受到自动分号插入的影响,并且可能会导致应用程序中的值递增或递减的无声错误。 使用
num + = 1
而不是num ++
或num ++
语句来表达你的值也是更有表现力的。 禁止一元增量和减量语句还会阻止您无意地预增/预减值,这也会导致程序出现意外行为。
|
|
variables–linebreak
在赋值的时候避免在 =
前/后换行。 如果你的赋值语句超出 max-len
, 那就用小括号把这个值包起来再换行。 eslint operator-linebreak
.
Why? 在
=
附近换行容易混淆这个赋值语句。
|
|
variables–no-unused-vars
不允许有未使用的变量。 eslint: no-unused-vars
Why? 一个声明了但未使用的变量更像是由于重构未完成产生的错误。这种在代码中出现的变量会使阅读者迷惑。
|
|
Hoisting
hoisting–about
var
声明会被提前到他的作用域的最前面,它分配的值还没有提前。const
和 let
被赋予了新的调用概念时效区 —— Temporal Dead Zones (TDZ)。 重要的是要知道为什么 typeof不再安全.
|
|
hoisting–anon-expressions
匿名函数表达式和 var
情况相同
|
|
hoisting–named-expresions
已命名函数表达式提升他的变量名,不是函数名或函数体
|
|
hoisting–declarations
函数声明则提升了函数名和函数体
|
|
Comparison Operators & Equality
comparison–eqeqeq
用 ===
和 !==
而不是 ==
和 !=
. eslint: eqeqeq
comparison–if
条件语句如’if’语句使用强制`ToBoolean’抽象方法来评估它们的表达式,并且始终遵循以下简单规则:
- Objects 计算成 true
- Undefined 计算成 false
- Null 计算成 false
- Booleans 计算成 the value of the boolean
- Numbers
- +0, -0, or NaN 计算成 false
- 其他 true
- Strings
''
计算成 false- 其他 true
|
|
comparison–shortcuts
布尔值用缩写,而字符串和数字要明确比较对象
|
|
comparison–moreinfo
更多信息请见Angus Croll的真理、平等和JavaScript —— Truth Equality and JavaScript
comparison–switch-blocks
在case
和default
分句里用大括号创建一块包含语法声明的区域(e.g. let
, const
, function
, and class
). eslint rules: no-case-declarations
.
Why? 语法声明在整个
switch
的代码块里都可见,但是只有当其被分配后才会初始化,他的初始化时当这个case
被执行时才产生。 当多个case
分句试图定义同一个事情时就出问题了
|
|
comparison–nested-ternaries
三元表达式不应该嵌套,通常是单行表达式。
eslint rules: no-nested-ternary
.
|
|
comparison–unneeded-ternary
避免不需要的三元表达式
eslint rules: no-unneeded-ternary
.
|
|
comparison–no-mixed-operators
用圆括号来混合这些操作符。 只有当标准的算术运算符(+
, -
, *
, & /
), 并且它们的优先级显而易见时,可以不用圆括号括起来。 eslint: no-mixed-operators
Why? 这提高了可读性,并且明确了开发者的意图
|
|
Blocks
blocks–braces
用大括号包裹多行代码块。 eslint: nonblock-statement-body-position
|
|
blocks–cuddled-elses
if
表达式的else
和if
的关闭大括号在一行。 eslint: brace-style
|
|
blocks–no-else-return
如果 if
语句中总是需要用 return
返回, 那后续的 else
就不需要写了。 if
块中包含 return
, 它后面的 else if
块中也包含了 return
, 这个时候就可以把 return
分到多个 if
语句块中。 eslint: no-else-return
|
|
Control Statements
control-statements
当你的控制语句(if
, while
等)太长或者超过最大长度限制的时候, 把每一个(组)判断条件放在单独一行里。 逻辑操作符放在行首。
Why? 把逻辑操作符放在行首是让操作符的对齐方式和链式函数保持一致。这提高了可读性,也让复杂逻辑更容易看清楚。
|
|
control-statements–value-selection
不要用选择操作符代替控制语句。
|
|
Comments
comments–multiline
多行注释用 /** ... */
|
|
comments–singleline
单行注释用//
,将单行注释放在被注释区域上面。如果注释不是在第一行,那么注释前面就空一行
|
|
comments–spaces
所有注释开头空一个,方便阅读。 eslint: spaced-comment
|
|
comments–actionitems
在你的注释前使用FIXME'或
TODO’前缀, 这有助于其他开发人员快速理解你指出的需要重新访问的问题, 或者您建议需要实现的问题的解决方案。 这些不同于常规注释,因为它们是可操作的。 动作是FIXME: - 需要计算出来
或TODO: - 需要实现
。
comments–fixme
用// FIXME:
给问题做注释
|
|
comments–todo
用// TODO:
去注释问题的解决方案
|
|
Whitespace
whitespace–spaces
tab用两个空格. eslint: indent
|
|
whitespace–before-blocks
在大括号前空一格。 eslint: space-before-blocks
|
|
whitespace–around-keywords
在控制语句(if
, while
等)的圆括号前空一格。在函数调用和定义时,参数列表和函数名之间不空格。 eslint: keyword-spacing
|
|
whitespace–infix-ops
用空格来隔开运算符。 eslint: space-infix-ops
|
|
whitespace–newline-at-end
文件结尾空一行. eslint: eol-last
|
|
|
|
|
|
whitespace–chains
当出现长的方法链(>2个)时用缩进。用点开头强调该行是一个方法调用,而不是一个新的语句。eslint: newline-per-chained-call
no-whitespace-before-property
|
|
whitespace–after-blocks
在一个代码块后下一条语句前空一行。
|
|
whitespace–padded-blocks
不要用空白行填充块。 eslint: padded-blocks
|
|
whitespace–in-parens
圆括号里不要加空格。 eslint: space-in-parens
|
|
whitespace–in-brackets
方括号里不要加空格。看示例。 eslint: array-bracket-spacing
|
|
whitespace–in-braces
花括号里加空格。 eslint: object-curly-spacing
|
|
whitespace–max-len
避免一行代码超过100个字符(包含空格)。
- 注意: 对于上面——strings–line-length,长字符串不受此规则限制,不应分解。 eslint:
max-len
Why? 这样确保可读性和可维护性
|
|
whitespace–block-spacing
作为语句的花括号内也要加空格 —— {
后和 }
前都需要空格。 eslint: block-spacing
|
|
whitespace–comma-spacing
,
前不要空格, ,
后需要空格。 eslint: comma-spacing
|
|
whitespace–computed-property-spacing
计算属性内要空格。参考上述花括号和中括号的规则。 eslint: computed-property-spacing
|
|
whitespace–func-call-spacing
调用函数时,函数名和小括号之间不要空格。 eslint: func-call-spacing
|
|
whitespace–key-spacing
在对象的字面量属性中, key
value
之间要有空格。 eslint: key-spacing
|
|
whitespace–no-trailing-spaces
行末不要空格。 eslint: no-trailing-spaces
whitespace–no-multiple-empty-lines
避免出现多个空行。 在文件末尾只允许空一行。 eslint: no-multiple-empty-lines
|
|
Commas
commas–leading-trailing
不要前置逗号。 eslint: comma-style
|
|
commas–dangling
额外结尾逗号: 要 eslint: comma-dangle
Why? 这导致git diffs更清洁。 此外,像Babel这样的转换器会删除转换代码中的额外的逗号,这意味着你不必担心旧版浏览器中的结尾逗号问题。
|
|
|
|
Semicolons
Yup. eslint: semi
Why? 当 JavaScript 遇到没有分号结尾的一行,它会执行自动插入分号
Automatic Semicolon Insertion
这一规则来决定行末是否加分号。如果JavaScript在你的断行里错误的插入了分号,就会出现一些古怪的行为。当新的功能加到JavaScript里后, 这些规则会变得更复杂难懂。显示的结束语句,并通过配置代码检查去捕获没有带分号的地方可以帮助你防止这种错误。
|
|
Type Casting & Coercion
coercion–explicit
在语句开始执行强制类型转换。
coercion–strings
Strings: eslint: no-new-wrappers
|
|
coercion–numbers
Numbers: 用 Number
做类型转换,parseInt
转换string常需要带上基数。 eslint: radix
|
|
coercion–comment-deviations
请在注释中解释为什么要用移位运算和你在做什么。无论你做什么狂野的事,比如由于 parseInt
是你的性能瓶颈导致你一定要用移位运算。 请说明这个是因为性能原因,
|
|
coercion–bitwise
注意: 用移位运算要小心. 数字使用64-位表示的,但移位运算常常返回的是32为整形source)。移位运算对大于32位的整数会导致意外行为。Discussion. 最大的32位整数是 2,147,483,647:
|
|
coercion–booleans
布尔:
|
|
Naming Conventions
naming–descriptive
避免用一个字母命名,让你的命名可描述。 eslint: id-length
|
|
naming–camelCase
用小驼峰式命名你的对象、函数、实例。 eslint: camelcase
|
|
naming–PascalCase
用大驼峰式命名类。 eslint: new-cap
|
|
naming–leading-underscore
不要用前置或后置下划线。 eslint: no-underscore-dangle
Why? JavaScript 没有私有属性或私有方法的概念。尽管前置下划线通常的概念上意味着“private”,事实上,这些属性是完全公有的,因此这部分也是你的API的内容。这一概念可能会导致开发者误以为更改这个不会导致崩溃或者不需要测试。 如果你想要什么东西变成“private”,那就不要让它在这里出现。
|
|
naming–self-this
不要保存引用this
, 用箭头函数或函数绑定——Function#bind.
|
|
naming–filename-matches-export
export default导出模块A,则这个文件名也叫A.*, import 时候的参数也叫A。 大小写完全一致。
|
|
naming–camelCase-default-export
当你export-default一个函数时,函数名用小驼峰,文件名需要和函数名一致。
|
|
naming–PascalCase-singleton
当你export一个结构体/类/单例/函数库/对象 时用大驼峰。
|
|
naming–Acronyms-and-Initialisms
简称和缩写应该全部大写或全部小写。
Why? 名字都是给人读的,不是为了适应电脑的算法的。
|
|
naming–uppercase
你可以用全大写字母设置静态变量,他需要满足三个条件。
- 导出变量
- 是
const
定义的, 保证不能被改变 - 这个变量是可信的,他的子属性都是不能被改变的
Why? 这是一个附加工具,帮助开发者去辨识一个变量是不是不可变的。
- 对于所有的
const
变量呢? —— 这个是不必要的。大写变量不应该在同一个文件里定义并使用, 它只能用来作为导出变量。 赞同!- 那导出的对象呢? —— 大写变量处在export的最高级(e.g.
EXPORTED_OBJECT.key
) 并且他包含的所有子属性都是不可变的。
|
|
Accessors
accessors–not-required
不需要使用属性的访问器函数。
accessors–no-getters-setters
不要使用JavaScript的getters/setters,因为他们会产生副作用,并且难以测试、维护和理解。相反的,你可以用 getVal()和setVal(‘hello’)去创造你自己的accessor函数
|
|
accessors–boolean-prefix
如果属性/方法是boolean
, 用 isVal()
或 hasVal()
|
|
accessors–consistent
用get()和set()函数是可以的,但是要一起用
|
|
Events
events–hash
通过哈希而不是原始值向事件装载数据时(不论是DOM事件还是像Backbone事件的很多属性)。 这使得后续的贡献者(程序员)想这个事件装载更多的数据时不用去找或者更新每个处理器。例如:
|
|
prefer:
|
|
jQuery
jquery–dollar-prefix
jQuery对象用$
变量表示。
|
|
jquery–cache
暂存jQuery查找
|
|
jquery–queries
DOM查找用层叠式$('.sidebar ul')
或 父节点 > 子节点 $('.sidebar > ul')
. jsPerf
jquery–find
用jQuery对象查询作用域的find
方法查询
|
|
ES5 兼容性
es5-compat–kangax
ECMAScript 6+ (ES 2015+) Styles
es6-styles
这是收集到的各种ES6特性的链接
- 箭头函数——Arrow Functions
- 类——Classes
- 对象缩写——Object Shorthand
- 对象简写——Object Concise
- 对象计算属性——Object Computed Properties
- 模板字符串——Template Strings
- 解构赋值——Destructuring
- 默认参数——Default Parameters
- Rest
- Array Spreads
- Let and Const
- 幂操作符——Exponentiation Operator
- 迭代器和生成器——Iterators and Generators
- 模块——Modules
tc39-proposals
不要用TC39 proposals, TC39还没有到 stage 3。
Why? 它还不是最终版, 他可能还有很多变化,或者被撤销。 我们想要用的是 JavaScript, 提议还不是JavaScript。
Standard Library
标准库中包含一些功能受损但是由于历史原因遗留的工具类
standard-library–isnan
用 Number.isNaN
代替全局的 isNaN
.
eslint: no-restricted-globals
Why? 全局
isNaN
强制把非数字转成数字, 然后对于任何强转后为NaN
的变量都返回true
如果你想用这个功能,就显式的用它。
|
|
standard-library–isfinite
用 Number.isFinite
代替 isFinite
.
eslint: no-restricted-globals
Why? 理由同上,会把一个非数字变量强转成数字,然后做判断。
|
|
Testing
testing–yup
Yup.
|
|
testing–for-real
No, but seriously:
- 无论用那个测试框架,你都需要写测试。
- 尽量去写很多小而美的纯函数,减少突变的发生
- 小心 stub 和 mock —— 这会让你的测试变得脆弱。
- 在 Airbnb 首选
mocha
。tape
偶尔被用来测试一些小的,独立的模块。 - 100%测试覆盖率是我们努力的目标,即便实际上很少达到。
- 每当你修了一个bug, 都要写一个回归测试。 一个bug修复了,没有回归测试,很可能以后会再次出问题。