Categories
JavaScript Best Practices

JavaScript Best Practices — Whitespaces, Underscores, and Useless Ternary

avaScript 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 useless whitespaces, whether to include underscores in identifier names and useless ternary expressions.

No Trailing Whitespace at the End of Lines

Trailing whitespaces are useless. They may be picked by source control systems which may identifier as a code change.

This causes frustration for developers since they expect real code differences rather than difference in whitespaces.

Trailing whitespaces are just taking up space and they should be removed.

Dangling Underscores in Identifiers

Dangling underscores in identifiers are good as long as they’re used to identify ‘private’ variables.

JavaScript doesn’t have truly private variables, so an underscore is useful for identifying variables that we shouldn’t access.

For instance, in a class, we can add ‘private’ variables that starts with an underscore to identify them that it shouldn’t be accessed.

We can write the code as follows:

class Person {
  constructor(name) {
    this._name = name;
  }

  get name() {
    return this._name;
  }
}

In the code above, we have this._name , which is a member of the Person class that we identify as private. We should instead use the name getter to access the value of this._name .

Therefore, this is useful for identifying a private variable before JavaScript classes have private members.

However, in other places, we shouldn’t be accessing some properties that start or end with underscores directly, like the __proto__ property.

For instance, we shouldn’t be changing the __proto__ property by reassigning it to a different value:

const foo = {};
foo.__proto__ = { a: 1 };

We shouldn’t be getting or setting the __proto__ property directly even though it exists and became a standard since ES6.

The __proto__ property has the prototype of the given object. In the code above, __proto__ has the prototype of foo .

To access the prototype of an object, we can use the Object.getPrototypeOf method as follows:

const foo = {};
const proto = Object.getPrototypeOf(foo);

The getPrototypeOf method returns the prototype, which is in an internal property of the specified object. It does the same thing as accessing the __proto__ property.

To set the prototype of an object, instead of assigning a new value to the __proto__ property, we should create a new object with the Object.create method.

For instance, we can use it as follows:

const bar = {
  a: 1
};
const foo = Object.create(bar);
foo.b = 1;

In the code above, we have the foo object, which is assigned to the object created by the Object.create method.

It sets the __proto__ property of foo to the bar object. Therefore, when we log it, we’ll see that the value of the a property in __proto__ is 1.

Other than identifying private variables in constructors or classes, then we probably shouldn’t use underscores in our code since they’re supposed to identify internal members or properties of a constructor or object.

Don’t Use Ternary Operators in Useless Ways

If we’re using the ternary operator to return true or false only, then we don’t need to use the ternary operator.

Instead, we can just remove the ? and everything else after it.

For instance, if we have the following code:

const foo = num === 1 ? true : false;

Then that just returns true is num is 1. Otherwise, if num isn’t 1, then it returns false .

We don’t need a ternary expression to do that, we can just write the following code:

const foo = num === 1;

num === 1 returns true if num is 1 and false otherwise.

Another example that we can simplify is the following:

const baz = bar ? bar : 1;

In the code above, we check if bar is truthy. If it’s truthy, then we return bar . Otherwise, we return 1. Then it assigns the returned value to baz .

We can simplify that with the || operator, which returns the first truthy operand that this operator is applied to.

If both of them aren’t truthy, then it returns the 2nd operand.

For instance, if we have the following code:

const baz = bar || 1;

Then it assigns bar to baz if it’s truthy. Otherwise, it assigns 1 to baz .

Therefore, this is simpler and does the same thing as the previous example.

Conclusion

Trailing whitespaces are useless and they should be removed. They just show in version control systems as code difference which frustrates developers.

Underscores can be used to identify private members in classes and constructors. However, most other uses are dubious.

Ternary operators that can be simplified, like the ones that returns true or false or check if a value is truthy and then returns itself or something else depending on that can be simplified.

Categories
JavaScript Best Practices

JavaScript Best Practices — ES6 Features and Regex

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 template tag spacing, wrapping regex literals, and arrow function bodies.

Spacing Between Template Tags and Their Literals

Since ES6, with the introduction of template strings, a new kind of function called template tags are introduced.

They only work with template strings. It’s a function that takes a few parameters including the template string itself and its parts.

We use template tags by defining a template literal tag and use it as follows:

const foo = (strings, ...args) => {
  console.log(strings, args);
}
`
const a = 1;
const b = 2;
foo`foo ${a} bar ${b}`

In the code above, we have defined the foo literal tag, which has the strings parameter that has an array of all the parts of the string that are static.

The args parameter is an array with all the values that are interpolated in the string.

Therefore, the value of string according to the console log output is [“foo “, “ bar “, “”, raw: Array(3)] , and the value of args is [1, 2] , which are the 2 values that we interpolated into the string.

Template literal tags are useful for taking the parts of a template string and then returning something from it.

Usually, we don’t have any spaces between the template literal tag name and the template string itself.

As we have in the code above, we have:

foo`foo ${a} bar ${b}`

which has no space between foo and the opening backtick so that it’s clear that we’re calling foo on the template string that immediately follows it.

Wrapping Regex Literals

Regex literals may be wrapped so that we’re clear that we’re calling a method on the regex literal.

For instance, if we want to call the exec function as follows:

const result = /foo/.exec("foo");

Then people may not know that we’re actually calling the exec method on it.

If we wrap the regex literal with parentheses, then we can write the following code:

const result = (/foo/).exec("foo");

Then it may be clearer for some people that we’re calling exec on the /foo/ regex literal.

This syntax is more of an optional suggestion than something that everyone should follow.

Braces in Arrow function Body

Arrow functions are functions that are shorter and don’t bind to variables like this or arguments .

Also, we can’t use them as constructors or use bind , call , or apply on it.

It also lets us write functions in a shorter way. One benefit of it is that if we return something on the same line as the signature of the arrow function, then we don’t need the keyword return to return the item at the end of the function.

Instead, whatever’s at the end of the function is returned.

For multiline arrow functions, the return syntax works the same way as any other function. We would need the return keyword to return something.

For instance, if we have the following code:

const foo = () => 2;

Then 2 is returned by the foo function.

If we want to return an object, we can write the following code:

const foo = () => ({
  a: 1,
  b: 2
});

In the code above, we return the object that we wrapped in parentheses, so when we call foo , we get:

{
  a: 1,
  b: 2
}

returned.

If we have a multiline function, then return syntax works the same way as any other function.

For instance, we write the following code to return something in a multiline function:

const foo = () => {
  return {
    a: 1,
    b: 2
  }
};

In the code above, we have the return statement in the second line of the foo function.

And we get the same result as the previous foo function if we call foo .

Therefore, for functions that return what it’ll return on the first line of the function, then we don’t need braces. Otherwise, we should add braces.

Conclusion

Regex literals may be wrapped in parentheses so that we’re clear that we’re calling a method on it.

Usually, we don’t put spaces between the template tag name and the template string literal so that we’re clear that we’re operating on it.

Arrow functions usually don’t have braces if they return something on the first line.

Otherwise, we need braces and the return keyword to return something.

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.