JavaScript
Le langage dynamique incontournable.
References JavaScript
Let instead of var
If you must reassign references, use let instead of var. Why? let is block-scoped rather than function-scoped like var.
var count = 1;
if (true) {
count += 1;
}
let count = 1;
if (true) {
count += 1;
}
Classes and constructor
Always use class
Classes are a new feature in ES6, used to describe the blueprint of an object and make EcmaScript’s prototypical inheritance model function more like a traditional class-based language. So always use class. Avoid manipulating prototype directly. Why ? class syntax is more concise and easier to reason about.
function Queue(contents = []) {
this.queue = [...contents];
}
Queue.prototype.pop = function () {
const value = this.queue[0];
this.queue.splice(0, 1);
return value;
};
class Queue {
constructor(contents = []) {
this.queue = [...contents];
}
pop() {
const value = this.queue[0];
this.queue.splice(0, 1);
return value;
}
}
Extends for inheritance
Use extends for inheritance. Why? It is a built-in way to inherit prototype functionality without breaking instanceof.
class PeekableQueue extends Queue {
peek() {
return this.queue[0];
}
}
Comparison operators and equality
Equality operators
Use === and !== over == and !=.
With these operators, you can :
- Comparing two literal values
- Evaluating the value of typeof
- Comparing against null
Coercion
Embrace implicit coercion when it makes sense. Avoid it otherwise.
if (x === undefined || x === null) { ... }
if (x == undefined) { ... } // Check if x is undefined and implicitly not null
Template strings
In traditional JavaScript, text that is enclosed within matching  » or ‘ marks is considered a string. Text within double or single quotes can only be on one line. There was no way to insert data into these strings. This resulted in a lot of ugly concatenation code that looked like:
var name = 'Sam';
var age = 42;
console.log('hello my name is ' + name + ' I am ' + age + ' years old');
ES6 introduces a new type of string literal that is marked with back ticks (`). These string literals can include newlines, and there is a string interpolation for inserting variables into strings:
var name = 'Sam';
var age = 42;
console.log(`hello my name is ${name}, and I am ${age} years old`);
Destructuring
Object destructuring
Use object destructuring when accessing and using multiple properties of an object. Why? Destructuring saves you from creating temporary references for those properties.
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return firstName + ' ' + lastName;
}
Good
function getFullName(user) {
const { firstName, lastName } = user;
return `${firstName} ${lastName}`;
}
Better
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
Array destructuring
const arr = [1, 2, 3, 4];
const first = arr[0];
const second = arr[1];
const arr = [1, 2, 3, 4];
const [first, second] = arr;
Functions
Never name a parameter arguments.
This will take precedence over the arguments object that is given to every function scope.
function foo(name, options, arguments) {
...
}
function foo(name, options, args) {
...
}
Never use arguments
Opt to use rest syntax … instead.
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
function concatenateAll(...args) {
return args.join('');
}
Default parameter
Use default parameter syntax rather than mutating function arguments.
function handleThings(opts) {
opts = opts || {};
...
}
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
...
}
function handleThings(opts = {}) {
...
}
Always put default parameters last.
function handleThings(opts = {}, name) {
...
}
function handleThings(name, opts = {}) {
...
}
Arrow function
Fat arrow (or arrow function)
When you must use function expressions (as when passing an anonymous function), use arrow function notation. Why ? It creates a version of the function that executes in the context of this, which is usually what you want, and is more concise syntax.
[1, 2, 3].map(function (x) {
const y = x + 1;
return x * y;
});
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
Functions that calculate a single expression and return its values can be defined even simpler:
incrementedItems = items.map(function (x) {
return x+1;
});
incrementedItems = items.map((x) => x+1);
There is one important difference, however: arrow functions do not set a local copy of this, arguments, super, or new.target. When this is used inside an arrow function JavaScript uses the this from the outer scope.
