JavaScript风格指南摘抄(自己尚不熟悉的)
Objects
one place
Use computed property names when creating objects with dynamic property names.
Why? They allow you to define all the properties of an object in one place.
1 | function getKey(k) { |
group
Group your shorthand properties at the beginning of your object declaration.
Why? It’s easier to tell which properties are using the shorthand.
1 | const anakinSkywalker = 'Anakin Skywalker'; |
quote-props
Only quote properties that are invalid identifiers. eslint: quote-props
Why? In general we consider it subjectively easier to read. It improves syntax highlighting, and is also more easily optimized by many JS engines.
1 | // bad |
no-prototype-builtins
Do not call Object.prototype
methods directly, such as hasOwnProperty
, propertyIsEnumerable
, and isPrototypeOf
. eslint: no-prototype-builtins
Why? These methods may be shadowed by properties on the object in question - consider
{ hasOwnProperty: false }
- or, the object may be a null object (Object.create(null)
).
1 | // bad |
shallow-copy
Prefer the object spread operator over Object.assign
to shallow-copy objects. Use the object rest operator to get a new object with certain properties omitted.
1 | // very bad |
Arrays
copy arrays
Use array spreads ...
to copy arrays.
1 | // bad |
convert an iterable object
To convert an iterable object to an array, use spreads ...
instead of Array.from
.
1 | const foo = document.querySelectorAll('.foo'); |
convert an array-like object
Use Array.from
for converting an array-like object to an array.
1 | const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; |
mapping over iterables
Use Array.from
instead of spread ...
for mapping over iterables, because it avoids creating an intermediate array.
1 | // bad |
array-callback-return
Use return statements in array method callbacks. It’s ok to omit the return if the function body consists of a single statement returning an expression without side effects, following 8.2. eslint: array-callback-return
1 | // good |
Destructuring
object destructuring
Use object destructuring when accessing and using multiple properties of an object. eslint: prefer-destructuring
Why? Destructuring saves you from creating temporary references for those properties.
1 | // bad |
array destructuring
Use array destructuring. eslint: prefer-destructuring
1 | const arr = [1, 2, 3, 4]; |
multiple return values
Use object destructuring for multiple return values, not array destructuring.
Why? You can add new properties over time or change the order of things without breaking call sites.
1 | // bad |
Function
statements
ECMA-262 defines a block
as a list of statements. A function declaration is not a statement.
1 | // bad |
arguments
Never use arguments
, opt to use rest syntax ...
instead. eslint: prefer-rest-params
Why?
...
is explicit about which arguments you want pulled. Plus, rest arguments are a real Array, and not merely Array-like likearguments
.
1 | // bad |
default parameter syntax
Use default parameter syntax rather than mutating function arguments.
1 | // really bad |
default parameters last
Always put default parameters last.
1 | // bad |
Never mutate parameters
Never mutate parameters. eslint: no-param-reassign
Why? Manipulating objects passed in as parameters can cause unwanted variable side effects in the original caller.
1 | // bad |
Never reassign parameters
Never reassign parameters. eslint: no-param-reassign
Why? Reassigning parameters can lead to unexpected behavior, especially when accessing the
arguments
object. It can also cause optimization issues, especially in V8.
1 | // bad |
Arrow Function
wrap it in parentheses
In case the expression spans over multiple lines, wrap it in parentheses for better readability.
Why? It shows clearly where the function starts and ends.
1 | // bad |
Classes & Constructors
Always use class
Always use class
. Avoid manipulating prototype
directly.
Why?
class
syntax is more concise and easier to reason about.
1 | // bad |
Use extends for inheritance
Use extends
for inheritance.
Why? It is a built-in way to inherit prototype functionality without breaking
instanceof
.
1 | // bad |
method chaining
Methods can return this
to help with method chaining.
1 | // bad |
no-useless-constructor
Classes have a default constructor if one is not specified. An empty constructor function or one that just delegates to a parent class is unnecessary. eslint: no-useless-constructor
1 | // bad |
Modules
use modules (import/export)
Always use modules (import
/export
) over a non-standard module system. You can always transpile to your preferred module system.
Why? Modules are the future, let’s start using the future now.
1 | // bad |
not use wildcard imports
Do not use wildcard imports.
Why? This makes sure you have a single default export.
1 | // bad |
do not directly
And do not export directly from an import.
Why? Although the one-liner is concise, having one clear way to import and one clear way to export makes things consistent.
1 | // bad |
import/no-mutable-exports
Do not export mutable bindings. eslint: import/no-mutable-exports
Why? Mutation should be avoided in general, but in particular when exporting mutable bindings. While this technique may be needed for some special cases, in general, only constant references should be exported.
1 | // bad |
import/prefer-default-export
In modules with a single export, prefer default export over named export. eslint: import/prefer-default-export
Why? To encourage more files that only ever export one thing, which is better for readability and maintainability.
1 | // bad |
Iterators and Generators
Prefer higher-order functions
Don’t use iterators. Prefer JavaScript’s higher-order functions instead of loops like for-in
or for-of
. eslint: no-iterator
no-restricted-syntax
Why? This enforces our immutable rule. Dealing with pure functions that return values is easier to reason about than side effects.
Use
map()
/every()
/filter()
/find()
/findIndex()
/reduce()
/some()
/ … to iterate over arrays, andObject.keys()
/Object.values()
/Object.entries()
to produce arrays so you can iterate over objects.
1 | const numbers = [1, 2, 3, 4, 5]; |
generator-star-spacing
If you must use generators, or if you disregard our advice, make sure their function signature is spaced properly. eslint: generator-star-spacing
Why?
function
and*
are part of the same conceptual keyword -*
is not a modifier forfunction
,function*
is a unique construct, different fromfunction
.
1 | // good |
Properties
dot-notation
Use dot notation when accessing properties. eslint: dot-notation
1 | const luke = { |
bracket notation
Use bracket notation []
when accessing properties with a variable.
1 | const luke = { |
exponentiation operator
Use exponentiation operator **
when calculating exponentiations. eslint: no-restricted-properties
.
1 | // bad |
Variables
no-multi-assign
Don’t chain variable assignments. eslint: no-multi-assign
Why? Chaining variable assignments creates implicit global variables.
1 | // bad |
Comparison Operators & Equality
shortcuts for
Use shortcuts for booleans, but explicit comparisons for strings and numbers.
1 | // bad |
Commas
Additional trailing comma
Additional trailing comma: Yup. eslint: comma-dangle
Why? This leads to cleaner git diffs. Also, transpilers like Babel will remove the additional trailing comma in the transpiled code which means you don’t have to worry about the trailing comma problem in legacy browsers.
1 | // bad - git diff without trailing comma |
Type Casting & Coercion
Strings
Strings: eslint: no-new-wrappers
1 | // => this.reviewScore = 9; |
Numbers
Numbers: Use Number
for type casting and parseInt
always with a radix for parsing strings. eslint: radix
no-new-wrappers
1 | const inputValue = '4'; |
Booleans
Booleans: eslint: no-new-wrappers
1 | const age = 0; |
Naming Conventions
Use camelCase
Use camelCase when you export-default a function. Your filename should be identical to your function’s name.
1 | function makeStyleGuide() { |
Use PascalCase
Use PascalCase when you export a constructor / class / singleton / function library / bare object.
1 | const AirbnbStyleGuide = { |