Removed code guides since we have eslint --fix and sass-lint
This commit is contained in:
parent
38567045ad
commit
dd0e73e283
2 changed files with 0 additions and 706 deletions
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
title: CSS Quality Guide
|
|
||||||
---
|
|
||||||
|
|
||||||
Coming soon
|
|
|
@ -1,701 +0,0 @@
|
||||||
---
|
|
||||||
title: JavaScript Quality Guide
|
|
||||||
---
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
|
|
||||||
This style guide aims to provide the ground rules for an application's JavaScript code, such that it's highly readable and consistent across different developers on a team. The focus is put on quality and coherence across the different pieces of your application.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
1. [Modules](#modules)
|
|
||||||
2. [Strict Mode](#strict-mode)
|
|
||||||
3. [Spacing](#spacing)
|
|
||||||
4. [Semicolons](#semicolons;)
|
|
||||||
5. [Linting](#linting)
|
|
||||||
6. [Strings](#strings)
|
|
||||||
7. [Variable Declaration](#variable-declaration)
|
|
||||||
8. [Conditionals](#conditionals)
|
|
||||||
9. [Equality](#equality)
|
|
||||||
10. [Ternary Operators](#ternary-operators)
|
|
||||||
11. [Functions](#functions)
|
|
||||||
12. [Prototypes](#prototypes)
|
|
||||||
13. [Object Literals](#object-literals)
|
|
||||||
14. [Array Literals](#array-literals)
|
|
||||||
15. [Regular Expressions](#regular-expressions)
|
|
||||||
16. [Comments](#comments)
|
|
||||||
17. [Variable Naming](#variable-naming)
|
|
||||||
18. [Everyday Tricks](#everyday-tricks)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Modules
|
|
||||||
|
|
||||||
The most common module systems are [CommonJS](https://wiki.commonjs.org/wiki/CommonJS), [AMD](https://requirejs.org/docs/whyamd.html), and [ES6 Modules](https://eviltrout.com/2014/05/03/getting-started-with-es6.html). Modules systems provide individual scoping, avoid leaks to the `global` object, and improve code base organization by **automating dependency graph generation**, instead of having to resort to manually creating multiple `<script>` tags.
|
|
||||||
|
|
||||||
Module systems also provide us with dependency injection patterns, which are crucial when it comes to testing individual components in isolation.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Strict Mode
|
|
||||||
|
|
||||||
**Always** put [`"use strict";`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode) at the top of your modules. Strict mode allows you to catch nonsensical behavior, discourages poor practices, and _is faster_ because it allows compilers to make certain assumptions about your code.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Spacing
|
|
||||||
|
|
||||||
Spacing must be consistent across every file in the application. To this end, using something like [`.editorconfig`](https://editorconfig.org) configuration files is highly encouraged. Here are the defaults used for [lbry.tech](https://lbry.tech):
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# .editorconfig
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
end_of_line = lf
|
|
||||||
indent_size = 2
|
|
||||||
indent_style = space
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
```
|
|
||||||
|
|
||||||
The `.editorconfig` file takes care of creating the desired spacing for this project by pressing the tab key.
|
|
||||||
|
|
||||||
Spacing doesn't just entail tabbing, but also the spaces before, after, and in between arguments of a function declaration. Here are some examples of the spacing scheme we employ:
|
|
||||||
|
|
||||||
```js
|
|
||||||
function () {}
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
function (a, b) {}
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
function namedFunction(a, b) {}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Semicolons`;`
|
|
||||||
|
|
||||||
We love using semicolons to avoid potential issues with Automatic Semicolon Insertion _(ASI)_ and to save us from ourselves.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Linting
|
|
||||||
|
|
||||||
Linting is great for ensuring basic mistakes don't get merged into master (like unnecessary or unintentional semicolons). We use [`eslint`](https://github.com/eslint/eslint) to ensure our next-generation JavaScript code is up to snuff.
|
|
||||||
|
|
||||||
Here is our `.eslintrc.json` file:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"es6": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended"
|
|
||||||
],
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2017,
|
|
||||||
"sourceType": "module",
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"experimentalObjectRestSpread": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"indent": ["error", 2, { "SwitchCase": 1 }],
|
|
||||||
"linebreak-style": ["error", "unix"],
|
|
||||||
"quotes": ["error", "double"],
|
|
||||||
"semi": ["error", "always"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Strings
|
|
||||||
|
|
||||||
Strings should always be quoted using the same quotation mark throughtout a codebase. Be consistent! We prefer double-quotes.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
const message = 'oh hai ' + name + "!";
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
const message = "oh hai " + name + "!";
|
|
||||||
```
|
|
||||||
|
|
||||||
You'll be a happier JavaScript developer if you use template literals. That way it'll be far easier to format your strings, and the code looks a lot cleaner too.
|
|
||||||
|
|
||||||
#### Better
|
|
||||||
|
|
||||||
```js
|
|
||||||
const message = util.format(`oh hai ${name}!`);
|
|
||||||
```
|
|
||||||
|
|
||||||
To declare multi-line strings, particularly when dealing with HTML snippets, template literals definitely come in handy!
|
|
||||||
|
|
||||||
```js
|
|
||||||
const html = `
|
|
||||||
<div>
|
|
||||||
<span class='monster'>${name}</span>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Variable Declaration
|
|
||||||
|
|
||||||
Always declare variables in **a consistent manner**, and at the top of their scope. Keeping variable declarations to _one per line is encouraged_. Comma-first, a single `var` statement, multiple `var` statements, it's all fine, just be consistent across the project, and ensure the team is on the same page.
|
|
||||||
|
|
||||||
Knowing when to use [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const), [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) and [`var`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var) is super important.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
const foo = 1,
|
|
||||||
bar = 2;
|
|
||||||
|
|
||||||
let baz;
|
|
||||||
let pony;
|
|
||||||
|
|
||||||
let a
|
|
||||||
, b;
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
const foo = 1;
|
|
||||||
|
|
||||||
if (foo > 1) {
|
|
||||||
var bar = 2;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
const foo = 1;
|
|
||||||
const bar = 2;
|
|
||||||
|
|
||||||
let baz;
|
|
||||||
let pony;
|
|
||||||
|
|
||||||
let a;
|
|
||||||
let b;
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
const foo = 1;
|
|
||||||
let bar;
|
|
||||||
|
|
||||||
if (foo > 1) {
|
|
||||||
bar = 2;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Variable declarations that aren't immediately assigned a value are acceptable to share the same line of code.
|
|
||||||
|
|
||||||
#### Acceptable
|
|
||||||
|
|
||||||
```js
|
|
||||||
const a = "a";
|
|
||||||
const b = 2;
|
|
||||||
|
|
||||||
let i, j;
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Conditionals
|
|
||||||
|
|
||||||
If you are one-lining conditionals, the conditional should be a) short and b) without brackets. Otherwise, brackets are enforced for the sake of text comprehension.
|
|
||||||
|
|
||||||
#### Acceptable
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (err) throw err;
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Better
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Equality
|
|
||||||
|
|
||||||
Avoid using `==` and `!=` operators, always favor `===` and `!==`. These operators are called the "strict equality operators," while [their counterparts will attempt to cast the operands](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) into the same value type.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
function isEmptyString (text) {
|
|
||||||
return text == "";
|
|
||||||
}
|
|
||||||
|
|
||||||
isEmptyString(0);
|
|
||||||
// <- true
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
function isEmptyString(text) {
|
|
||||||
return text === "";
|
|
||||||
}
|
|
||||||
|
|
||||||
isEmptyString(0);
|
|
||||||
// <- false
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Ternary Operators
|
|
||||||
|
|
||||||
Ternary operators are fine for clear-cut conditionals, but unacceptable for confusing choices. As a rule, if you can't eye-parse it as fast as your brain can interpret the text that declares the ternary operator, chances are it's probably too complicated for its own good.
|
|
||||||
|
|
||||||
Use operators responsibly.
|
|
||||||
|
|
||||||
jQuery is a prime example of a codebase that's [**filled with nasty ternary operators**](https://github.com/jquery/jquery/blob/d7237896c79a5a10d85fcdec199c5657a469a92b/src/ajax.js#L125).
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
function calculate(a, b) {
|
|
||||||
return a && b ? 11 : a ? 10 : b ? 1 : 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
function getName (mobile) {
|
|
||||||
return mobile ? mobile.name : "Generic Player";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In cases that may prove confusing just use `if` and `else` statements instead. If you have more than three `if`/`else` statements, [switch cases](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch) are the way to go for readability/comprehension.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
When declaring a function, always use the [function declaration form](https://stackoverflow.com/a/336868/1167646) instead of [function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function). Because [hoisting](https://github.com/buildfirst/buildfirst/tree/master/ch05/04_hoisting).
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
const sum = (x, y) => {
|
|
||||||
return x + y;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
function sum(x, y) {
|
|
||||||
return x + y;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
That being said, there's nothing wrong with function expressions that are just [currying another function](http://ejohn.org/blog/partial-functions-in-javascript).
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
const plusThree = sum.bind(null, 3);
|
|
||||||
```
|
|
||||||
|
|
||||||
Keep in mind that [function declarations will be hoisted](https://github.com/buildfirst/buildfirst/tree/master/ch05/04_hoisting) to the top of the scope so it doesn't matter the order they are declared in. That being said, you should make sure to avoid placing them inside conditional statements.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (Math.random() > 0.5) {
|
|
||||||
sum(1, 3);
|
|
||||||
|
|
||||||
function sum(x, y) {
|
|
||||||
return x + y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (Math.random() > 0.5) {
|
|
||||||
sum(1, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sum(x, y) {
|
|
||||||
return x + y;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
function sum(x, y) {
|
|
||||||
return x + y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Math.random() > 0.5) {
|
|
||||||
sum(1, 3);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If you need a _"no-op"_ method you can use either `Function.prototype`, or `function noop () {}`. Ideally a single reference to `noop` is used throughout the application.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Don't declare functions inside of loops.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
const values = [1, 2, 3];
|
|
||||||
|
|
||||||
for (let i = 0; i < values.length; i++) {
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log(values[i]);
|
|
||||||
}, 1000 * i);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
const values = [1, 2, 3];
|
|
||||||
|
|
||||||
for (let i = 0; i < values.length; i++) {
|
|
||||||
setTimeout(i => {
|
|
||||||
return function () {
|
|
||||||
console.log(values[i]);
|
|
||||||
};
|
|
||||||
}(i), 1000 * i);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
const values = [1, 2, 3];
|
|
||||||
|
|
||||||
for (let i = 0; i < values.length; i++) {
|
|
||||||
setTimeout(i => {
|
|
||||||
console.log(values[i]);
|
|
||||||
}, 1000 * i, i);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
const values = [1, 2, 3];
|
|
||||||
|
|
||||||
for (let i = 0; i < values.length; i++) {
|
|
||||||
wait(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
function wait(i) {
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log(i);
|
|
||||||
}, 1000 * i);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Better
|
|
||||||
|
|
||||||
```js
|
|
||||||
const values = [1, 2, 3];
|
|
||||||
|
|
||||||
for (const value of values) {
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log(value);
|
|
||||||
}, 1000 * value);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Whenever a method is non-trivial, make the effort to **use a named function declaration rather than an anonymous function**. This will make it easier to pinpoint the root cause of an exception when analyzing stack traces.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
function once(fn) {
|
|
||||||
let ran = false;
|
|
||||||
|
|
||||||
return function () {
|
|
||||||
if (ran) return;
|
|
||||||
|
|
||||||
ran = true;
|
|
||||||
fn.apply(this, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
function once(fn) {
|
|
||||||
let ran = false;
|
|
||||||
|
|
||||||
return function run() {
|
|
||||||
if (ran) return;
|
|
||||||
|
|
||||||
ran = true;
|
|
||||||
fn.apply(this, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Avoid keeping indentation levels from raising more than necessary by using guard clauses instead of flowing `if` statements.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (car) {
|
|
||||||
if (black) {
|
|
||||||
if (turbine) {
|
|
||||||
return "Batman!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (condition) {
|
|
||||||
// 10+ lines of code
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (!car) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!black) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!turbine) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Batman!";
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (!condition) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 10+ lines of code
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Prototypes
|
|
||||||
|
|
||||||
Hacking native prototypes should be avoided at all costs, use a method instead.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
String.prototype.half = function () {
|
|
||||||
return this.substr(0, this.length / 2);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
function half(text) {
|
|
||||||
return text.substr(0, text.length / 2);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Avoid prototypical inheritance models** unless you have a very good _performance reason_ to justify yourself.
|
|
||||||
|
|
||||||
- Prototypical inheritance boosts puts need for `this` through the roof
|
|
||||||
- It's way more verbose than using plain objects
|
|
||||||
- It causes headaches when creating `new` objects
|
|
||||||
- Needs a closure to hide valuable private state of instances
|
|
||||||
- Just use plain objects instead
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Object Literals
|
|
||||||
|
|
||||||
Instantiate using curly braced notation `{}` and use factories instead of constructors. Here's a proposed pattern for you to implement objects in general.
|
|
||||||
|
|
||||||
```js
|
|
||||||
function util(options) {
|
|
||||||
// private methods and state go here
|
|
||||||
let foo;
|
|
||||||
|
|
||||||
function add() {
|
|
||||||
return foo++;
|
|
||||||
}
|
|
||||||
|
|
||||||
function reset() { // note that this method isn't publicly exposed
|
|
||||||
foo = options.start || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset();
|
|
||||||
|
|
||||||
return {
|
|
||||||
// public interface methods go here
|
|
||||||
uuid: add
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Array Literals
|
|
||||||
|
|
||||||
Instantiate using the square bracketed notation `[]`. If you have to declare a fixed-dimension array for performance reasons then it's fine to use the `new Array(length)` notation instead.
|
|
||||||
|
|
||||||
It's about time you master array manipulation! [Learn about the basics](https://ponyfoo.com/articles/fun-with-native-arrays). It's way easier than you might think.
|
|
||||||
|
|
||||||
- [`.forEach`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
|
|
||||||
- [`.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice)
|
|
||||||
- [`.splice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)
|
|
||||||
- [`.join`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join)
|
|
||||||
- [`.concat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat)
|
|
||||||
- [`.unshift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)
|
|
||||||
- [`.shift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)
|
|
||||||
- [`.push`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push)
|
|
||||||
- [`.pop`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop)
|
|
||||||
|
|
||||||
Learn and abuse the functional collection manipulation methods. These are **so** worth the trouble.
|
|
||||||
|
|
||||||
- [`.filter`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
|
|
||||||
- [`.map`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
|
|
||||||
- [`.reduce`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
|
|
||||||
- [`.reduceRight`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight)
|
|
||||||
- [`.some`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
|
|
||||||
- [`.every`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every)
|
|
||||||
- [`.sort`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
|
|
||||||
- [`.reverse`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Regular Expressions
|
|
||||||
|
|
||||||
Keep regular expressions in variables, don't use them inline. This will vastly improve readability.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
if (/\d+/.test(text)) {
|
|
||||||
console.log("so many numbers!");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
const numeric = /\d+/;
|
|
||||||
|
|
||||||
if (numeric.test(text)) {
|
|
||||||
console.log("so many numbers!");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Also [learn how to write regular expressions](https://ponyfoo.com/articles/learn-regular-expressions), and what they actually do. Then you can also [visualize them online](https://regexr.com).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Comments
|
|
||||||
|
|
||||||
For code that isn't super obvious, we write comments to explain what it does. The exception to that rule is explaining what a regular expression does.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
// create the centered container
|
|
||||||
const p = $("<p/>");
|
|
||||||
|
|
||||||
p.center(div);
|
|
||||||
p.text("foo");
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
const container = $("<p/>");
|
|
||||||
const contents = "foo";
|
|
||||||
|
|
||||||
container.center(parent);
|
|
||||||
container.text(contents);
|
|
||||||
|
|
||||||
megaphone.on("data", value => {
|
|
||||||
container.text(value); // the megaphone periodically emits updates for container
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
const numeric = /\d+/; // one or more digits somewhere in the string
|
|
||||||
|
|
||||||
if (numeric.test(text)) {
|
|
||||||
console.log("so many numbers!");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Variable Naming
|
|
||||||
|
|
||||||
Variables have meaningful names so that we don't have to resort to commenting what a piece of functionality does. We try to be expressive while succinct, and use meaningful variable names.
|
|
||||||
|
|
||||||
#### Bad
|
|
||||||
|
|
||||||
```js
|
|
||||||
function a(x, y, z) {
|
|
||||||
return z * y / x;
|
|
||||||
}
|
|
||||||
|
|
||||||
a(4, 2, 6);
|
|
||||||
// <- 3
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Good
|
|
||||||
|
|
||||||
```js
|
|
||||||
function ruleOfThree(had, got, have) {
|
|
||||||
return have * got / had;
|
|
||||||
}
|
|
||||||
|
|
||||||
ruleOfThree(4, 2, 6);
|
|
||||||
// <- 3
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Everyday Tricks
|
|
||||||
|
|
||||||
We use `||` to define default values. If the left-hand value is [falsy](https://j11y.io/javascript/truthy-falsey) then the right-hand value will be used.
|
|
||||||
|
|
||||||
```js
|
|
||||||
function a(value) {
|
|
||||||
const defaultValue = 33;
|
|
||||||
const used = value || defaultValue;
|
|
||||||
}
|
|
||||||
```
|
|
Loading…
Reference in a new issue