Categories
JavaScript Best Practices

JavaScript Best Practices — Data and Objects

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at the best practices when working with different types of data and objects.

Primitive Types

There’re different kinds of primitive types in JavaScript. They’re strings, numbers. booleans. null, undefined. symbol, and bigint.

The symbol data type is new to ES6, so we should make sure that we convert them to ES5 code. It can’t be polyfilled so it must be converted to code that’s compatible with the platforms we’re targeting in the final build artifact.

Bigint is also new and can’t be polyfilled. If we use it, we should also transpile it to something that’s compatible with our targeted platforms in the final build artifact.

Use const Instead of var

const lets us define constants in JavaScript code. It’s available since ES6. Once it’s defined, it can’t be assigned to a new value. However, the assigned value is still mutable.

It’s also block-scoped so that we can only access constants inside the block. Unlike variables declared with var , it’s not hoisted so we can reference it before it’s defined.

var is also function scoped, so it can be accessed outside the block.

Therefore, const is better than var .

If we don’t need to reassign something to a different value, then use const .

Otherwise, use let .

We can use them as follows:

const a = 1;
let b = 1;
b = 2;

We should never write something like the following in our code:

var c = 1;

Objects

When we create new objects, we should use the object literal syntax instead of the Object constructor. It’s much shorter and does the same thing.

They both create objects that inherit from the Object constructor.

For instance, instead of writing:

const obj = new Object();

In the code above, we used the new operator with the Object constructor to create an object, which isn’t necessary.

We write the following instead:

const obj = {};

Using the constructor makes us type more characters that we don’t need in our code.

Using Computed Property Names with Creating Dynamic Property Names

Since ES6, we can have dynamic property names in the objects we define. We define computed property keys with brackets around our computed key.

For instance, we can write the following code to do that:

const getKey = (k) => {
  return `foo ${k}`;
}
`
const obj = {
  [getKey('bar')]: 1
}

In the code above, have a getKey function that’s used to return a computed key that we put into the obj object to be used as a property key.

This way, we define an object with computed property keys the shortest and clearest way possible.

This is better than using the bracket notation after the object is defined. For instance, we wouldn’t want to write:

const getKey = (k) => {
  return `foo ${k}`;
}
`
const obj = {};
obj[getKey('bar')] = 1;

because it’s longer and we have to write obj multiple times.

Photo by Mikhail Vasilyev on Unsplash

Use the Object Method Shorthand

Another great ES6 feature is the object method shorthand. It allows us to create a method without using the function keyword.

In the old way, we create a method within an object as follows:

const cat = {
  name: 'james',
  greet: function() {
    return `hi ${this.name}`;
  }
}

In the code above, we used the function keyword to define the greet method within the cat object.

The better way to do it is with the object method shorthand as follows:

const cat = {
  name: 'james',
  greet() {
    return `hi ${this.name}`;
  }
}

The code above does the same thing as the previous example, but we omitted the function keyword.

We can also do the same thing for generator functions. Instead of writing:

const foo = {
  gen: function*() {
    yield 2;
  }
}

We write:

const foo = {
  * gen() {
    yield 2;
  }
}

They both have the gen generator method, but we omitted the function keyword in the second example.

Conclusion

We should use ES6 features whenever possible. Good features that we should use include the object method shorthand, computed property keys if we need dynamically generated object key names, and the const keyword.

If we use new data types like symbols and bigints, we should make sure that they work in the platforms that we’re targeting.

Categories
JavaScript Best Practices

JavaScript Best Practices — Semicolons, Spacing, and Sorting

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we look at spacing around semicolons, statements, and functions and sorting object keys and variables.

Spacing Before and After Semicolons

We don’t need spacing before the semicolon but we do need spacing after it since we want to keep different statements apart.

For instance, the following code isn’t good since it has no spaces between the statements:

let a = 1;let b = 2;

As we can see, with a space character between the ; and the let keyword, it’s very hard to read the 2 let variable declarations.

On the other hand, if we added a space after the semicolon as follows:

let a = 1; let b = 2;

Then we can see the 2 variable declarations much more clearly.

Therefore, we should always add a space character after the semicolon if we have multiple statements on the same line.

Having a space character after the semicolon and before the next statement is the most common place to put the space character.

Sorting Object Keys

To make finding object keys easier, we may want to sort the keys by alphabetical order in an object.

For instance, we can write the following code to do that:

const obj = {  
  a: 1,  
  b: 2  
}

In the code above, we sorted the keys of obj by alphabetical order. This is more of a suggestion if we want to find object keys. However, it isn’t a big deal if the keys aren’t sorted.

Variable Sorting

Like with object keys, we can also sort variable declarations by alphabetical order so that we can find them easier.

Like with sorting object keys, it’s more of a suggestion than a requirement.

For instance, we can sort variable declarations as follows:

let a, b, c;

Space Before Blocks

We probably want a space before the block so that we can clearly see the function signature and the opening of the block.

For instance, we can write the following code to do that:

const foo = () => {};

In the code above, we have a space character before and after the arrow so that we can clearly see each part of our arrow function.

For traditional functions, we can see the following code:

const foo = function() {}

We have one space character between the parentheses and the opening curly brace. This also makes the code clearer than without any space.

Spaces make things easier to read.

Likewise, we can apply similar spacing to loops as follows:

for (let i = 0; i < 10; i++) {  
  console.log(i);  
}

In the code above, we have a space between the closing parentheses and the opening curly brace.

Again. This lets our eyes tell between different parts of the loop.

For try...catch , we usually have spacing like the following:

try {} catch (ex) {}

Having a little space just makes reading the code much easier.

Space Before Function Parenthesis

We usually don’t have a space character before the opening parenthesis since we have one space character after the closing parenthesis.

For instance, we usually define a JavaScript function as follows:

const foo = function() {};

As we can see, we have no space before between the function keyword and the opening parenthesis and one space character after the closing parenthesis and the opening curly brace.

Named functions have the same spacing. For instance, we write a named function as follows:

function foo() {};

We have one space character after the closing parenthesis and the opening curly brace.

Photo by Guillermo Ferla on Unsplash

Spaces Inside of Parentheses

We usually don’t put spaces between the parentheses and the expressions inside.

For instance, we usually don’t write something like:

const foo = ( 5 + 6 ) * 3;

The code above has an extra space before the 5 and after the 6. Instead, we usually, write expressions like that without those spaces as follows:

const foo = (5 + 6) * 3;

Conclusion

Usually, JavaScript code’s spacing follows some generally accepted conventions. We don’t have spaces between parentheses and expressions.

Between the function signature and the opening curly braces, we usually have space.

After a semicolon and before the next statement, we also usually have a space character to separate the 2 statements that are both in one line.

Categories
JavaScript Best Practices

JavaScript Best Practices — Tabs and Arithmetic

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at the use of the ++ and -- operators in JavaScript and replacing tabs with spaces.

The Unary Operators ++ and --

The ++ and -- operators let us increment and numeric variable by 1.

For instance, if we have the following code:

let x = 1;
x++;

Then x is first assigned to one, and then it becomes 2 because x++ increases it by 1.

The ++ operator can also be used before a variable. For instance, we can write the following code:

let x = 1;
++x;

The code above also assigns the variable to 1 first. Then it increases the variable x to 2.

The difference between using it before the variable and using it after is that when it’s added after the variable, then it increments and returns the value before incrementing.

If it’s used before the variable, then it increments and returns the value after incrementing.

That made no difference before or after in our case because we didn’t assign it to any variable.

However, if we’re assigning it to a variable or constant, then it matters. For instance, if we have the following code:

let x = 1;
const y = ++x;

Then x and y are both 2 since x ‘s latest value is returned after it’s incremented and then the latest value is assigned to y .

On the other hand, if we have the following code:

let x = 1;
const y = x++;

Then x is 2 and y is 1 since x ‘s old value is returned when the increment operation is being done, so it’s the old value of 1 is assigned to y .

-- is similar to ++ except that it decrements the variable by 1 rather than incrementing it by 1.

We can see that the similar result as ++ if the -- is applied before or after the variable.

Therefore, whether ++ or -- comes before or after the variable matters.

Spaces also matter. We shouldn’t have any spaces whether the operators are added before or after the variable.

For instance, we shouldn’t write code like the following:

let x = 1;
let y = 1;
x
++
y;

In the code above x stays as 1 but y is 2 because the JavaScript interpreter interprets it as the following:

let x = 1;
let y = 1;
x
++y;

Therefore, y is incremented, but x isn’t.

To make increment and decrement operations clearer, we can instead write the following:

let x = 1;
x += 1;

Then x is increment by 1, so x becomes 2.

This also works for incrementing x by any number. So we can write something like:

let x = 1;
x += 2;

to increment x by 2.

There’re also corresponding operators for subtraction, multiplication or division.

For instance, we can write the following for subtraction:

let x = 1;
x -= 2;

For multiplication, we can write:

let x = 1;
x *= 2;

and for division, we can write the following:

let x = 1;
x /= 2;

These are clearer that ++ or -- , so we should also consider using these operators to arithmetic operations in addition to assigning the new value to the same variable.

No Tab Characters

Tab characters are a pain. They aren’t consistent in all operating systems or text editors.

Therefore, we should think twice about using tabs in our code. Using tabs saves typing, but creates issues with inconsistencies of their spacing between operating systems and text editors.

One good way to keep using the tab key to save typing is to convert them to 2 spaces.

Spaces are almost always consistent with most text editors and operating systems. Therefore, there won’t be any issues with spacing when we opening the same file in different text editors or operating system utilities.

Conclusion

The ++ and -- operators may bring confusion. They can be added before or after a variable and they act differently as to when the updated value is returned.

If these operators are applied before the variable, then the newest value is returned right away so that we can assign the updated to another variable.

On the other hand, the value is returned value would still be the old value, so if we try to assign to a variable, it would be assigned the old value.

They both increment, but the returned value for them is different.

Tab characters shouldn’t be used in our code. If we want to save typing, we should convert tabs to spaces automatically.

Categories
JavaScript Best Practices

JavaScript Best Practices — Property Names and Semicolons

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at the best ways to add properties to objects and adding semicolons to our JavaScript code.

Quotes Around Object Literal Property Names

We should add quotes around object literal property names only when the property isn’t valid as property name if it’s not written as a string.

For instance, we don’t put quotes around the property of the following object because the property name is a valid identifier.

If we have the following object:

const foo = {
  a: 1
};

Then we don’t need quotes around a since a is already a valid identifier name in JavaScript.

In JavaScript, identifiers are case-sensitive and can contain Unicode letters, $ , _ and digits. However, a valid JavaScript identifier may not start with a digit.

If we want to name a property with an identifier that breaks any of the rules outlined above, then we need to put them around quotes so that they’re written as strings.

For instance, if we want to have a property name that has a space between 2 words, we can write the following code:

const foo = {
  'foo bar': 1
};

In the code, we have the foo object, which has the property 'foo bar' , which has to be in quotes because of the space between foo and bar .

Then we can only access it by using the bracket notation as follows:

foo['foo bar']

to get the value of the property.

Therefore, if it’s a valid identifier, then we don’t need quotes around the property name. Otherwise, we do, and we can only access it with the bracket notation.

Consistent Use of Backticks, Double, or Single Quotes in Strings

Out of all 3 string delimiters, the backtick is the most versatile since we can use it to create both template strings and regular strings.

Template strings let us interpolate expressions into out string instead of having to concatenate expressions with multiple substrings

Interpolation is just much easier to read and type than string concatenation. The amount of the code we’ve to write is much less since we don’t need the concatenation operator everywhere.

For instance, we instead of writing:

const baz = 1;
const foo = 'foo ' + baz + ' bar';

We can instead write the string above as a template string as follows:

const baz = 1;
const foo = `foo ${baz} bar`;

In the code above, we put in the expression baz into the template string instead of concatenating.

Reading and typing template strings are both easier.

With template strings, we don’t always have to interpolate expressions, we can just create a regular string like:

const foo = `foo bar`;

Also, we can use both single and double quotes within our string without having to escape it with a backslash.

For instance, we can write the following code to use single and double quotes together as a character in a string rather than a string delimiter:

const foo = `'foo' "bar"`;

This is another advantage of using backticks as string delimiter since single and double quotes are used more in sentences and clauses. However, backtick isn’t a commonly used English punctuation symbol.

Therefore, backticks are great as a string delimiter. It’s even better since we use backticks to create JavaScript template strings which can have JavaScript expressions interpolated in it.

Single and double quotes are good for quoting text.

Photo by Lukáš Vaňátko on Unsplash

Adding Our Own Semicolons is Better than Automatic Semicolon Insertion (ASI)

When we write JavaScript code, we should always write out the semicolons explicitly instead of relying on the automatic semicolon insertion capability to insert them for us automatically.

ASI doesn’t always insert them in the place that we want it to. For instance, if we have the following code:

const foo = () => {
  return
  {
    name: "foo"
  }
}

Then it’s going to be interpreted as:

const foo = () => {
  return;
  {
    name: "foo"
  };
}

Therefore when we call foo , it’s going to return undefined .

We probably don’t want that, so we should put in the semicolons ourselves as follows:

const foo = () => {
  return {
    name: "foo"
  };
}

Conclusion

We only need quotes around property names for property names that aren’t valid JavaScript identifier names.

Backticks is the best string delimiter since it can create template strings and regular string and leave single and double quotes as quote delimiters instead of string delimiters.

Categories
JavaScript Best Practices

JavaScript Best Practices— Padding, Exponentiation, and Spread

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at padding between statements, exponentiation, and spread.

Padding Lines Between Statements

We don’t need an empty line between all statements. We just need blank lines between groups of unrelated statements.

For instance, one way to group statements in a function is to write something like the following code:

for (let i = 0; i < 10; i++) {
  console.log(i);
}

for (let j = 0; j < 5; j++) {
  console.log(i);
}

In the code above, we have a blank line between the 2 for loops because each loop is its own logical group.

We just need a blank line between groups of statements that we want to group together. The blank line tells us that they should be read as a group.

Otherwise, a blank line is a waste of space and we can remove them to save vertical space.

Use of Math.pow Versus the ** Operator

Math.pow is a method that lets us do exponentiation in all versions of JavaScript since the first version up to the present version.

It takes 2 arguments, which are the base and the exponent and returns the base raised to the given exponent.

For instance, we can use it as follows:

const a = Math.pow(2, 3);

Then we get that a is 8 since 2 is raised to the power of 3.

It also works with fractional and negative powers. For instance, we can write:

const a = Math.pow(2, 0.5);

and get that a is 1.4142135623730951. We can also write:

const a = Math.pow(2, -1);

and get that a is 0.5.

In addition, we can put expressions in place of numbers as follows:

const x = 1,
  y = 2,
  z = 3;
const a = Math.pow(x + y, z);

Then we get that a is 27 because x is 1, y is 2 and c is 3 so we’re raising the base 3 to the power of 3.

With ES2015, the exponential operator is introduced. It’s denoted by ** .

We can use it to do exponentiation as follows:

const a = 2 ** 3;

and get that a is 8.

Fractional and negative powers and exponents all work as we expected with the ** operator. For instance, we can write to them as follows:

const a = 2 ** 0.5;
const b = 2 ** -1;

For expressions, we can write:

const x = 1,
  y = 2,
  z = 3;
const a = (x + y) ** z;

As we can see, using the exponentiation operator is shorter and we get the same result and it’s also more readable than calling a method that we don’t need to call.

We saved lots of typing and do the same thing, so we should use the exponentiation operator instead of calling Math.pow for doing exponentiation.

Use Object Spread Operator Over Calling Object.assign

The spread operator works on objects since ES2018. It lets us do a shallow copy of objects or merged multiple objects into one new object.

Between ES6 and ES2017, we’ve to use the Object.assign to merge multiple objects into one or make a shallow copy of it.

With Object.assign , we make a shallow copy of an object by writing the following code:

const foo = {
  a: 1
};
const bar = Object.assign({}, foo);

In the code above, we defined the foo object. Then we called Object.assign with an empty object as the first argument and the foo object as the 2nd argument to return a shallow copy of the foo object.

A shallow copy is where only the top-level properties are copied. The nested objects still reference the original object.

If we log the expressions foo === bar , it returns false , which means that foo and bar aren’t referencing the same object in memory. Therefore, we know that we made a shallow copy of the object.

The first argument of Object.assign is the target object to copy to and the rest of arguments, which can be as many as we want, are the source objects that we want to copy into the target object.

To merge multiple objects together with Object.assign , we just pass in more objects into it as arguments.

For instance, we can write the following code:

const foo = {
  a: 1
};
const baz = {
  b: 2
};
const qux = {
  c: 3
};
const bar = Object.assign({}, foo, baz, qux);

Then we get that bar is {a: 1, b: 2, c: 3} .

The spread operator makes this simpler. With it, we don’t have to call a function to merge and make shallow copies of objects. All we have to do is to use the spread operator, which is denoted by ... as follows:

const foo = {
  a: 1
};
const baz = {
  b: 2
};
const qux = {
  c: 3
};
const bar = {
  ...foo,
  ...baz,
  ...qux
};

The code above also merges all the objects into one as we did with Object.assign above.

And so we get that bar is {a: 1, b: 2, c: 3} .

We can make a shallow copy of an object as follows:

const foo = {
  a: 1
};
const bar = {
  ...foo,
};

and we get that bar is { a: 1 } but foo and bar aren’t equal when compared with the === operator as they don’t reference the same object.

Conclusion

The spread and exponentiation operator should be used instead of their older counterparts.

We don’t need a line after each statement. We need a new blank line after a group of statements that we want to group together.