# JavaScript best practices
# coding style
# articles
- JavaScript_best_practises : qooxdoo.org
- JavaScript : Douglas Crockford
- Onze idées fausses sur l'héritage en JavaScript : sylvainpv.developpez.com - 20150523 (trad article Eric Elliott)
- The Complete JavaScript Handbook - medium.freecodecamp.org - 20181030
Table of Contents
- ECMAscript
- ES6
- ES2016
- ES2017
- ES2018
- Coding Style
- Lexical Structure
- Variables
- Types
- Expressions
- Prototypal Inheritance
- Classes
- Exceptions
- Semicolons
- Quotes
- Template Literals
- Functions
- Arrow Functions
- Closures
- Arrays
- Loops
- Events
- The Event Loop
- Asynchronous Programming and Callbacks
- Promises
- Async and Await
- Loops and Scope
- Timers
- This
- Strict Mode
- Immediately-Invoked Function Expressions (IFFE’s)
- Math Operators
- The Math Object
- ES modules
- CommonJS
- Glossary
# perfs
Intensive JavaScript - developer.mozilla.org
By default the browser uses a single thread to run all the JavaScript in your page as well as to perform layout, reflows, and garbage collection. This means that long-running JavaScript functions can block the thread, leading to an unresponsive page and a bad user experience.
You can use the Frame rate and Waterfall tools to see when JavaScript is causing performance problems, and to single out the particular functions that need attention.
In this article we'll take an example site whose long-running JavaScript causes responsiveness problems, and apply two different approaches to fixing them. The first is to split long-running functions into pieces and use
requestAnimationFrame
to schedule each piece, and the second is to run the whole function in a separate thread using a web worker.
# undefined & null check
# JavasScript strict mode
Strict mode : developer.mozilla.org
Le mode strict apporte quelques changements à la sémantique « normale » de JavaScript :
- le mode strict élimine quelques erreurs silencieuses de JavaScript en les changeant en erreurs explicites (une exception sera levée)
- le mode strict corrige les erreurs qui font qu'il est difficile pour les moteurs JavaScript d'effectuer des optimisations (exécution plus rapide)
- le mode strict interdit les mot-clés susceptibles d'être définis dans les futures versions de ECMAScript
# online tools
# when to avoid if
and switch
Avoiding If Statements in Our JavaScript Code - medium.com - John Au-Yeung - 20200504
# ternary operator
const bar = foo ? 'foo' : 'bar';
instead of
const bar = ((foo) => {
if (foo) {
return 'foo'
}
return 'bar'
})(foo);
2
3
4
5
6
# short circuit
# with &&
const isOnline = true;
const makeRequest = () => {
//...
}
isOnline && makeRequest();
2
3
4
5
6
instead of
const isOnline = true;
const makeRequest = () => {
//...
}
if (isOnline) {
makeRequest();
}
2
3
4
5
6
7
8
# with ||
const bar = foo || 'abc';
instead of
const bar = ((foo) => {
if (!foo) {
return 'abc'
}
return foo;
})(foo)
2
3
4
5
6
# avoid switch
const descs = {
'border': 'kind dog',
'pitbull': 'angry dog',
'german': 'smart dog',
}
const desc = descs['border'];
2
3
4
5
6
7
instead of
const getDescription = (breed) => {
switch (breed) {
case 'border':
return 'kind dog';
case 'pitbull':
return 'angry dog';
case 'german':
return 'smart dog';
default:
return ''
}
}const desc = getDescription('border');
2
3
4
5
6
7
8
9
10
11
12
even with the default value
const desc = descs['foo'] || '';
# array iteration
Loop through an array in JavaScript : stackoverflow.com
For-each over an array in JavaScript? : stackoverflow.com
Array.forEach n’est pas toujours la meilleure solution ! - blog.overnetcity.com - 20140829
# array
/ object
/ Map
/ Set
# definitions
# array
const fruits = ['Apple', 'Banana'];
console.log(fruits.length);
// 2
2
3
4
It's an indexed list.
Never use the new constructor (const list = new Array();
), always use directly the literal (const list = [];
).
The constructor is slower and there is a common mistake with it, when an array is instantiated with only one arg you define the array length, and not an array of one element :
const list = new Array(2); // the array contains in fact [undefined, undefined], but const list = new Array(1, 2) leads to [1, 2]
.
Resize automatically. Order preserved ('cause indexed). Any types in it. Values can be duplicated (const list = [1, 2, 2, 2, 'toto'];
)
See MDN for details.
# object
const fruit = { name: 'Apple' };
See Object initializer in MDN for details with new
keyword or Object.create()
function.
The const object = new Object();
is rarely used.
The const object = Object.create(proto);
is used to create an object based on a proto
prototype. const object = Object.create(null);
allows object creation without any prototype.
An object is a key/value dictionnary.
A key must be unique and a string (or a Symbol). Keys are unordered, use Map instead if you need to keep an order.
Values can be of any types.
Can't get the size (numbers of K/V) easily.
# Map
var myMap = new Map();
var keyString = 'a string',
keyObj = {},
keyFunc = function() {};
// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, 'value associated with keyObj');
myMap.set(keyFunc, 'value associated with keyFunc');
myMap.size; // 3
// getting the values
myMap.get(keyString); // "value associated with 'a string'"
myMap.get(keyObj); // "value associated with keyObj"
myMap.get(keyFunc); // "value associated with keyFunc"
myMap.get('a string'); // "value associated with 'a string'"
// because keyString === 'a string'
myMap.get({}); // undefined, because keyObj !== {}
myMap.get(function() {}) // undefined, because keyFunc !== function () {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
A key must be unique and from any type (including function).
Keys are ordered.
There is a size()
function to get the K/V number.
Map is iterable.
A Map may perform better in scenarios involving frequent addition and removal of key pairs.
# Set
const set1 = new Set([1, 2, 3, 4, 5]);
console.log(set1.has(1));
// expected output: true
// ...
// iterate a Set
for (let item of mySet) console.log(item);
2
3
4
5
6
7
8
9
Set
objects are collections of values. You can iterate through the elements of a set in insertion order. A value in the Set
may only occur once; it is unique in the Set
's collection.
Set
, more familiar as a Math concept, is an abstract data type which contains only distinct elements/objects without the need of being allocated orderly by index.
A Set
is fundamentally different with an Array
, a Set
is a keyed collection where an Array
is an indexed collection.
Indexed collections are collections of data which are ordered by an index value
Keyed collections are collections which use keys; these contain elements which are iterable in the order of insertion.
# articles
Array in Indexed collections article - MDN
Maps and Sets in Key collections article - MDN
Map vs Object — What and when? - Maya Shavin - medium.com - 20180201
Set vs Array — What and when? - Maya Shavin - medium.com - 20180124
# async
/ await
Coder l’asynchrone en JavaScript (Par Matthieu Lux)
Tasks, microtasks, queues and schedules - jakearchibald.com - 20150817
In summary:
- Tasks execute in order, and the browser may render between them
- Microtasks execute in order, and are executed:
- after every callback, as long as no other JavaScript is mid-execution
- at the end of each task
Commentaire SylvainPV sur dev.com (fil privé) :
Ce qu'il faut retenir, c'est qu'un
Promise.resolve
n'entraîne pas de "vrai asynchronisme", c'est-à-dire qu'il n'attend pas la prochaine boucle d'événements. On a besoin d'attendre la boucle d'événements pour laisser le navigateur faire le rendu et ne pas avoir de freeze.
TLDR :
The
async
keyword before a function has two effects:
- Makes it always return a promise.
- Allows to use
await
in it.The
await
keyword before a promise makes JavaScript wait until that promise settles, and then:
- If it’s an error, the exception is generated, same as if
throw error
were called at that very place.- Otherwise, it returns the result, so we can assign it to a value.
Together they provide a great framework to write asynchronous code that is easy both to read and write.
With
async/await
we rarely need to writepromise.then/catch
, but we still shouldn’t forget that they are based on promises, because sometimes (e.g. in the outermost scope) we have to use these methods. AlsoPromise.all
is a nice thing to wait for many tasks simultaneously.
# drawbacks
How to escape async/await hell
TLDR : use successives
await
when not needed, the program control flow should continue. UsePromise.all
when needed.
# design patterns
The Comprehensive Guide to JavaScript Design Patterns - www.toptal.com - Marko Mišura - 201803xx
Learning JavaScript Design Patterns - Volume 1.7.0 - Addy Osmani - 2017
Table of Content
- Introduction
- What is a Pattern?
- "Pattern"-ity Testing, Proto-Patterns & The Rule Of Three
- The Structure Of A Design Pattern
- Writing Design Patterns
- Anti-Patterns
- Categories Of Design Pattern
- Summary Table Of Design Pattern Categorization
- JavaScript Design Patterns
- Constructor Pattern
- Module Pattern
- Revealing Module Pattern
- Singleton Pattern
- Observer Pattern
- Mediator Pattern
- Prototype Pattern
- Command Pattern
- Facade Pattern
- Factory Pattern
- Mixin Pattern
- Decorator Pattern
- Flyweight Pattern
- JavaScript MV* Patterns
- MVC Pattern
- MVP Pattern
- MVVM Pattern
- Modern Modular JavaScript Design Patterns
- AMD
- CommonJS
- ES Harmony
- Design Patterns In jQuery
- Composite Pattern
- Adapter Pattern
- Facade Pattern
- Observer Pattern
- Iterator Pattern
- Lazy Initialization Pattern
- Proxy Pattern
- Builder Pattern
- jQuery Plugin Design Patterns
- JavaScript Namespacing Patterns
- Conclusions
- References
# class
How to Use Classes and Sleep at Night - Dan Abramov - 20151015
Problem :
- Classes obscure the prototypal inheritance at the core of JS.
- Classes encourage inheritance but you should prefer composition.
- Classes tend to lock you into the first bad design you came up with.
How to use classes and sleep at night :
- Resist making classes your public API.
- Don’t inherit more than once.
- Don’t make
super
calls from methods. - Don’t expect people to use your classes.
- Learn functional programming
Applied to React :
- You can use
class
in your JS if you don’t inherit twice and don’t usesuper
. - Prefer to write React components as pure functions when possible.
- Use ES6 classes for components if you need the state or lifecycle hooks.
- In this case, you may only extend
React.Component
directly. - Give your feedback to the React team on the functional state proposals.