Thi's avatar
HomeAboutNotesBlogTopicsToolsReading
About|My sketches |Cooking |Cafe icon Support Thi
💌 [email protected]

JavaScript Best Practices

Anh-Thi Dinh
JavaScriptBest Practices
Left aside

References

  • Guidelines for writing JavaScript code examples - The MDN Web Docs project | MDN
  • Google JavaScript Style Guide

Special characters

Modules

Avoid using default exports, as they allow inconsistent naming during import.

Formatting

Empty blocks,
Where to break line → a higher syntactic level,
Horizontal alignment: discouraged.

JSDoc

Using markdown,

String

No line continuations,

Array

Create a new array,
When adding new item to an array (given const arr = [];),

Comments

Add an empty line before a comment. Comments should describe the purpose of the following code block.
Multi-line comments
But we use /* */ in below case,

Functions

Use camelCase for function names,
Use function declaration over function expression or arrow function,
Use arrow function in callback,
When using arrow functions, use implicit return when possible,

Loops

Prefer to use for...of and forEach instead of classical for (;;)
 
Use const in for...of and use let in other loops.
When you need to consider index,

Control statements

Continue right after if, don’t use else
Use braces for control flows and loops,
Don’t add break after return in switch
Use default as the last case, don’t use break with it.
Use brackets {} if you define a local variable inside each case.

Error handling

Use try...catch to catch error,
👍 Only recoverable errors should be catch!

Objects

Use PascalCase to define a class name and camelCase for the object property, methods and instances.
Use lirerals, not constructors to create a new object,
Use method definition syntax,
Use shorthand,
Don’t mix quoted and unquoted keys,

Operators

Prefer to use conditional ternary operator,
 
Use strict equality operator,
Use shortcuts for boolean tests,
Use optional chaining ?.

Variables

Naming,
Use let or const, not var to declare a new variable!
Declare one variable per line,
Void implicit type coercions,
To be continued…
◆References◆Special characters◆Modules◆Formatting◆JSDoc◆String◆Array◆Comments◆Functions◆Loops◆Control statements◆Error handling◆Objects◆Operators◆Variables
About|My sketches |Cooking |Cafe icon Support Thi
💌 [email protected]
1// Do
2const units = 'μs';
1// Don't
2const units = '\u03bcs'; // Greek letter mu, 's'
1// Do
2const output = '\ufeff' + content;  // byte order mark
1// Don't (no idea what this is)
2const output = '\ufeff' + content;
1// Do
2export class Foo {...}
3
4// Or
5class Foo {...}
6export { Foo };
1// Don't
2export default class Foo {...}
1// Do
2function doNothing() {}
1// Don't
2function doNothing() {
3	// ...
4}
1// Do
2const currentEstimate =
3    calc(currentEstimate + x * currentEstimate) /
4        2.0;
1// Don't
2const currentEstimate = calc(currentEstimate + x *
3    currentEstimate) / 2.0;
1// Do
2{
3  tiny: 42, // this is great
4  longer: 435, // this too
5};
1// Don't
2{
3  tiny:   42,  // permitted, but future edits
4  longer: 435, // may leave it unaligned
5};
1// Do
2/**
3 * Computes weight based on three factors:
4 *
5 *  - items sent
6 *  - items received
7 *  - last timestamp
8 */
1// Don't (it will appear as a single line instead)
2/**
3 * Computes weight based on three factors:
4 *   items sent
5 *   items received
6 *   last timestamp
7 */
1// Do
2const longString = 'This is a very long string that far exceeds the 80 ' +
3    'column limit. It does not contain long stretches of spaces since ' +
4    'the concatenated strings are cleaner.';
1// Don't
2const longString = 'This is a very long string that far exceeds the 80 \
3    column limit. It unfortunately contains long stretches of spaces due \
4    to how the continued lines are indented.';
1// Do
2const arr = [];
1// Don't
2const arr = new Array(length);
1// Do
2arr.push(1);
1// Don't
2arr[arr.length] = 1;
1// Do: leave a space
1//Don't: no space
1function checkout(goodsPrice, shipmentPrice, taxes) {
2  // Calculate the total price
3  const total = goodsPrice + shipmentPrice + taxes;
4
5  // Create and append a new paragraph to the document
6  const para = document.createElement("p");
7  para.textContent = `Total price is ${total}`;
8  document.body.appendChild(para);
9}
1// Do
2function exampleFunc(fruitBasket) {
3  console.log(fruitBasket); // ['banana', 'mango', 'orange']
4}
5
6// Or do (if it's too long)
7function exampleFunc(fruitBasket) {
8  console.log(fruitBasket);
9  // ['banana', 'mango', 'orange', 'apple', 'pear', 'durian', 'lemon']
10}
1// Don't
2function exampleFunc(fruitBasket) {
3  // Logs: ['banana', 'mango', 'orange']
4  console.log(fruitBasket);
5}
1// Do
2// Comment can be in 
3// multiple lines
1/* Don't
2   Use for multiple line 
3   like this */
1array.forEach((value /* , index, array */) => {
2  // …
3});
1// Do
2function sayHello() {
3  console.log("Hello!");
4}
1// Don't
2function SayHello() {
3  console.log("Hello!");
4}
5
6function doIt() {
7  console.log("Hello!");
8}
1// Do
2function sum(a, b) {
3  return a + b;
4}
1// Don't
2let sum = function (a, b) {
3  return a + b;
4};
5
6// Don't
7const x = () => {
8  // …
9};
1// Do
2const array1 = [1, 2, 3, 4];
3const sum = array1.reduce((a, b) => a + b);
1// Don't
2const array1 = [1, 2, 3, 4];
3const sum = array1.reduce(function (a, b) {
4  return a + b;
5});
6
1// Do
2arr.map((e) => e.id);
1// Don't
2arr.map((e) => {
3  return e.id;
4});
1// Do
2for (const dog of dogs) {
3  console.log(dog);
4}
5
6// or
7dogs.forEach((dog) => {
8  console.log(dog);
9});
1// Don't
2for (let i = 0; i < dogs.length; i++) {
3  console.log(dogs[i]);
4}
1// Do
2gerbils.forEach((gerbil, i) => {
3  console.log(`Gerbil #${i}: ${gerbil}`);
4});
1// Don't
2for (let i = 0; i < gerbils.length; i++) {
3  console.log(`Gerbil #${i}: ${gerbils[i]}`);
4}
1// Do
2if (condition) {
3	// actions when true
4}
5// actions when false
1// Don't
2if (condition) {
3	// actions when true
4} else {
5	// actions when false
6}
1// Do
2for (const car of storedCars) {
3  car.paint("red");
4}
1// Don't
2for (const car of storedCars) car.paint("red");
1// Do
2switch (species) {
3  case "chicken":
4    return farm.shed;
5  case "horse":
6    return corral.entry;
7  default:
8    return "";
9}
1// Don't
2switch (species) {
3  case "chicken":
4    return farm.shed;
5    break;
6  case "horse":
7    return corral.entry;
8    break;
9  default:
10    return "";
11}
1switch (fruits) {
2  case "Orange": {
3    const slice = fruit.slice();
4    eat(slice);
5    break;
6  }
7  case "Apple": {
8    const core = fruit.extractCore();
9    recycle(core);
10    break;
11  }
12}
1try {
2  console.log(getResult());
3} catch (e) {
4  console.error(e);
5}
1// Do
2const obj = {}
1// Don't
2const obj = new Object()
1// Do
2const obj = {
3  foo() {
4    // …
5  },
6  bar() {
7    // …
8  },
9};
1// Don't
2const obj = {
3  foo: function () {
4    // …
5  },
6  bar: function () {
7    // …
8  },
9};
1// Do
2function createObject(name, age) {
3  return { name, age };
4}
1// Don't
2function createObject(name, age) {
3  return { name: name, age: age };
4}
1// Do
2const { width: 42, maxWidth: 43 };
1// Don't
2const { width: 42, 'maxWidth': 43 };
1// Do
2const x = condition ? 1 : 2;
1// Don't
2let x;
3if (condition) {
4  x = 1;
5} else {
6  x = 2;
7}
1// Do
2name === "Thi";
3age !== 25;
1// Don't
2name == "Shilpa";
3age != 25;
1// Do
2if (x)
3
4// Or 
5if (!y)
1// Don't
2if (x === true)
3
4// or don't
5if (y === false)
1// Do
2const name = company?.group?.team
3const firstElement = list?.[0]
1// Don't
2let name;
3if (company && company.group && company.group.team) {
4	name = company.group.team;
5}
1// Do
2const accelerometer = ...
3const cars = ...
4const a = ...
5const currencyName = ...
6const car = ...
1// Don't
2const accmtr = ...
3const carArray = ...
4const descriptiveVariable = ...
5const currency_name = ...
6const aCar = ...
1// Do
2const playerScore = 0;
3const speed = distance / time;
1// Don't
2const thisIsaveryLONGVariableThatRecordsPlayerscore345654 = 0;
3const s = d / t;
1// Do
2let var1;
3let var2;
4let var3 = 1;
5let var4 = 1;
1// Don't
2let var1, var2;
3let var3 = var4 = 1;
1// Do
2class Person {
3  #name;
4  #birthYear;
5
6  constructor(name, year) {
7    this.#name = String(name); // 👈
8    this.#birthYear = Number(year); // 👈
9  }
10}
1// Don't
2class Person {
3  #name;
4  #birthYear;
5
6  constructor(name, year) {
7    this.#name = "" + name; // ✋
8    this.#birthYear = +year; // ✋
9  }
10}