Categories
JavaScript Best Practices

JavaScript Best Practices: Objects

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There’re lots of tricky parts to JavaScript, so there’re many things to avoid. We can follow some best practices easily to make our JavaScript code easy to read.

In this piece, we look at how to deal with objects in an easily maintainable way. We go through the traps that we can fall into when we define objects.


Use Literals for Primitive Values

In JavaScript, there’re multiple ways to declare primitive variables. Primitive variables include variables of any type other than objects.

One way is to use literals like so:

let x = 1;  
let y = true;  
let z = '';

In the code above, we set the literal value for number, boolean, and string to each variable.

Alternatively, we can write:

let x = new Number(1);  
let y = new Boolean(true);  
let z = new String('');

We can also write:

let x = Number(1);  
let y = Boolean(true);  
let z = String('');

Of the three ways to declare primitive variables above, some ways are better than the others. The best ways are to set the literals directly. The other way is to use the functions as we have in the third example.

Why shouldn’t we use the constructor to create variables with primitive values? First, anything defined with the new operator will have the type ‘object’ even though they have primitive values. This makes comparison between these objects difficult.

For example, if we write:

new String('foo') === new String('foo')

We get false because they’re both of type ‘object’, and === will evaluate to false if two objects don’t have the same reference in JavaScript. This means comparison is difficult.

Comparing with == will also evaluate to false for the same reason.

Since they’re both of type ‘object’, it’s harder to know whether they’re actually strings, booleans, or numbers.

The other two ways are much better because they’ll get us the right type. For example, the following will get us the type ‘number’:

let x = 2;  
console.log(typeof x);

This also applies to other primitive data types.

There’re no reasons to use the new operator to declare things with primitive values. It just makes life harder.

Using new is also slower since the JavaScript interpreter has to do one more operation than necessary to declare something that has a primitive of type ‘object’.

The Number , String and Boolean functions are useful for converting objects from one type to another. For example, if we have:

let x = '2';

Then we can convert it to a number with a Number function as follows:

let y = Number(x);

Use Literals to Declare Objects Whenever They Exist

Some objects have literals associated with them. For example, arrays have the [...] literal. Regular expressions can be declared by surround patterns with slashes. Functions can be declared with the function keyword or using the fat arrow.

It’s confusing to define values with constructors sometimes. For example, arrays have two constructors. One has one parameter with the array length as the parameter. The other is a comma-separated list of entries.

This means that Array(1) will get us an empty array with length 1 and no content. On the other hand, Array(1,2,3) will get us [1,2,3].

As we can see, it’s just not as clear to declare an array by using the constructor.

For functions, we have the function keyword or Function constructor.

Using the Function constructor doesn’t make sense since we have to pass strings that have the code for our functions and strings for the parameter names. It opens things up for code injection attacks, and it’s a pain to write code as a string.

The function keyword is much more clear. And it lets us write code that’s recognized by text editors as function code. There’s no reason to declare a function with the Function constructor unless we want to define a function that has dynamic code.

Likewise, the RegExp constructor is good for constructing regular expression objects dynamically, but otherwise is the same as the regular expression literal. The regular expression literal and constructor are the same for static regular expressions, so there’s some use for the constructor.

The Object constructor just makes us type more code than object literals; otherwise, they’re the same. This means it’s kind of pointless to use it to declare objects.


Automatic Type Conversions

For primitive values, JavaScript can convert things to different types depending on the context.

For example, suppose we have:

1 == '1'

Then the string 1 will be converted to a number.

Suppose we have:

1 + '1'

Then the number 1 will be converted to a string so that we get '11'. JavaScript just assumes that we’re concatenating.

On the other hand, suppose we write:

1 - '1'

We get 0 because it assumes that we’re subtracting two numbers.

Suppose we write:

1 - 'a'

Because the result isn’t a number, we get NaN since we can’t subtract a number with a non-numeric string.

In an expression that evaluates to a boolean, the variables or values inside are evaluated to their truthy or falsy values.

Falsy values include:

  • 0
  • null
  • undefined
  • empty string
  • false
  • NaN

Everything else is truthy. Suppose we have the following:

0 || undefined || null || 1

We get 1. The JavaScript interpreter evaluates all the falsy values and returns 1 since that’s the last thing left.

To make sure we get the types we expect, we should convert everything to the type that we actually expect or we should check for the type.

To convert primitive values like numbers, booleans, and strings, we can use the Number , Boolean , and String functions respectively. We just pass in whatever objects to these functions.

We can also use the + sign before something to convert it to a number.

!! also converts things to boolean according to their truthiness. The first exclamation mark converts the value according to its truthiness and then negates it. Then the second exclamation mark converts it back to the original truthiness value.

To check the type of primitive values, we can use the typeof operator. However, note that null has the type ‘object’. Everything has the type that we expect.


In most cases, object literals are the clearest way to define objects. The only exceptions are when we need functions with dynamically generated code or regular expressions that are dynamically generated. We should never use the new keyword to declare things that have primitive values. Finally, we should be careful of automatic type conversions and check the types or convert them according to our needs.

Categories
JavaScript Best Practices

JavaScript Best Practices — Unexpected Values and More

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There are lots of tricky parts to JavaScript, and there are many things to avoid. We can follow some best practices to make our JavaScript code easy to read.

In this article, we look at the best way to compare objects and function parameters, adding a default value to switch statements and function parameters and avoiding the use of the eval function.

Use === For Comparing Objects

In JavaScript, there are 2 operators for equality comparison. One is the == operator and the other is the === operator. == compares the operands by converting them to the same type automatically.

=== compares by both comparing the content and the type of both operands.

We want to use === because it compares both the type and the content so that we won’t get any mismatch in the type.

For example, if we use the == operator, we can the following expressions evaluated to true :

0 == "";  
0 == null;  
0 == undefined;  
null == undefined;  
1 == "1";

In the first 4 lines, everything is falsy so they’re all converted to false before comparing for equality with the == operator.

In the last line, '1' is converted to 1 before comparison so that we get the value true returned.

To avoid these confusing results, we can use the === operator, which compares both the type and the content of the values. With ===, everything above will be evaluated to false .

If we want to compare things with the same content and different types with the === operator, we can convert them to the same type first.

For example, if we want compare 1 and '1' , we can write:

+1 === +'1'

Then they’ll both be converted to 1 and the expression will evaluate to true.

This way, we don’t get anything with unexpected types being compared.

Default Parameters

JavaScript functions can take in any number of parameters even though they have their own signatures. This means that we can pass in fewer parameters than we expect.

With ES6, we get the default parameter value feature. This lets us set the default value for function parameters.

For example, we can write:

const add = (a, b = 0) => a + b;

Then we don’t have to pass in the second argument for the function to return a numerical value. If we write:

console.log(add(1));

We get 1 since the value of b will be set 0 if nothing is passed, so we get 1 + 0 which is 1.

Photo by Kristina Paparo on Unsplash

Add Default Value for Switch Statements

We should always add a default block to switch statements, since we might have unexpected values being passed into the switch statement.

For example, we should write:

const getDayName = (dayOfWeek) => {  
  let day;  
  switch (dayOfWeek) {  
    case 0:  
      day = "Sunday";  
      break;  
    case 1:  
      day = "Monday";  
      break;  
    case 2:  
      day = "Tuesday";  
      break;  
    case 3:  
      day = "Wednesday";  
      break;  
    case 4:  
      day = "Thursday";  
      break;  
    case 5:  
      day = "Friday";  
      break;  
    case 6:  
      day = "Saturday";  
      break;  
    default:  
      day = "Unknown";  
  }  
  return day;  
}

To get the day of the week, because we can pass in anything to the getDayName function. For example, we can write:

console.log(getDayName(0));  
console.log(getDayName(1));  
console.log(getDayName(1000));

If we pass in 1000, we need to handle that, so we need a default value.

Don’t Use Eval

The eval function accepts a string that contains JavaScript code, which will be run by this function.

We shouldn’t use it because it lets code from unknown sources run, which is a big security risk.

Also, it’s also slower than normal code since it’s interpreted on the fly. This is because the code can’t be optimized by JavaScript engines.

Modern interpreters convert code to machine code, which can’t be done with code passed into eval . This means that the interpreter has to do variable lookups on the fly to set things to the right variables.

Any operations that are done to variables will force the browser to re-evaluate the code again if it’s running code passed into the eval function.

Conclusion

When we compare objects for equality, we should use the === operator since it compares both the content and the type of the object. Also, we should put default values for parameters in case they aren’t passed into the function when it’s called. Also, we should add a default block to switch statements to deal with unexpected values. Finally, don’t use the eval function because it’s a big security that allows people to inject malicious code to our programs and it’s slow to run code with eval .

Categories
JavaScript Best Practices

JavaScript Best Practices — Variables

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There are lots of tricky parts to JavaScript, so there are many things to avoid.

We can follow some best practices to make our JavaScript code easy to read.

In this article, we look at how to declare variables in an easy-to-read way. Also, we look at ways to avoid declaring global variables and hiding private variables from the outside.


Avoid Global Variables

We should avoid the use of global variables as much as possible for various reasons.

One is that they’re easy to overwrite in different places since they’re available everywhere. They can also overwrite things in the window object since global variables are properties of the window object.

These two are real issues that make our code hard to follow. Therefore, we should define local variables as much as possible. We can define local variables by using the var, let, or const keywords.

Variables defined with var are available at the level where they are defined and below before they are defined. For example, if we write:

Then we get undefined for the first console.log and one for the second log.

It’s the same as writing:

Variables declared with let are available only after they’re defined, so if we gave:

We get the error:

Uncaught ReferenceError: Cannot access ‘x’ before initialization

With the const keyword, we define constants that can only be assigned once and never again. It’s also available only after it’s declared, unlike var.

For example, we can write:

const log = () => {  
  console.log(x);  
}

const x = 1;
log();


Calling `log` before `const x = 1` will also get us:

Uncaught ReferenceError: Cannot access ‘x’ before initialization


If we want variables that are available in different parts of a program, we should use JavaScript modules and then build the modules into one or several large files when we release our code. This is available since ES6.

We can `export` our variables and `import` it in other modules. There’s also `export default` to export the whole module. This way, we only export things that should be available outside the module and keep everything else private.

We can also use closures to keep variables inside a function so they can’t be accessed outside. An example of a simple closure would be:

const multiply = () => {
const x = 3;
return () => x * 2;
}


We keep `x` inside the `multiply` function so that it can’t be accessed outside and return a function that does something with it.

Then, we call it by writing:

console.log(multiply()());


* * *

### Always Declare Local Variables

As a corollary, we should always declare local variables. We should always declare local variables and constants with `var`, `let`, or `const`.

Otherwise, it’ll be declared as a global variable as a property of `window` which we definitely don’t want.

For example, we should never write:

x = 1;


Instead, we should write:

let x = 1;


Fortunately, JavaScript strict mode doesn’t allow undeclared variables, so we can’t accidentally create global variables.

Also, JavaScript modules have strict mode enabled by default so we also can’t define global variables accidentally in there.

![](https://cdn-images-1.medium.com/max/800/0*XDF6_FrkR3Js4-Cw)Photo by [Francesco De Tommaso](https://unsplash.com/@detpho?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

* * *

### Putting Variables and Constant Declarations on Top

Putting variable and constant declarations on top makes our code cleaner as everything is on top. It also stops us from accidentally referencing things declared with `let` or `const` before they are defined.

If strict mode is off, we also avoid defining global variables. And we also avoid accidental re-declarations of variables. Re-declarations should be caught by many text editors, but it’s still a possibility.

We can make multiple variable declarations in one line by separating variable names with commas. For example, we can write:

let x, y;
x = 1;
y = 1;
console.log(x, y);


Then we get:

1 1


From the `console.log`.

We can do the same for loops:

let i;

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

* * *

### Initialize Variables When Declaring Them

It’s a good idea to initialize our variables or constants with values when declaring them. It prevents undefined value errors, and we can both declare the variable or constant and set an initial value to it all in one line.

Otherwise, we have one line for declaring the variable or constant and another line for setting its value.

For example, we can write:

```
let x = 1,  
  y = 1;
```

To declare both `x` and `y`.

This is much shorter than writing:

```
let x;  
let y;  
x = 1;  
y = 1;
```

We can declare and initialize multiple variables by separating each declaration and assignment with a comma.

* * *

### Conclusion

Here are some basic best practices for declaring and initializing variables.

We looked at how to declare variables cleanly and how to avoid declaring global variables. There is a lot more to writing clean JavaScript programs so stay tuned for more.
Categories
JavaScript JavaScript Best Practices

JavaScript Best Practices — Modules and Identifiers

To make code easy to read and maintain, we should follow some best practices.

In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.

Minimum and Maximum Identifier Lengths

We should make identifier descriptive so they definitely shouldn’t be too short.

It also shouldn’t be too long.

If it’s too short, it’s probably not descriptive enough.

If it’s too long, then it has redundant information and takes up too much space.

So we shouldn’t write:

const x = 5;

since we don’t know what x is.

But we can write something like const numApples = 1; .

Location of Arrow Function Bodies with Implicit Returns

We should put arrows in a logical location.

For instance, we can write:

(foo) => bar;

or

(foo) => (bar);

or

(foo) => bar => baz;

They are conventional and logical.

It’s better than these examples:

(foo) =>  
  bar;

or:

(foo) =>  
  (bar);

The first examples are more compact than these ones.

Default Imports

We’ve have a default export for a default import to work.

For instance, we should write:

foo.js

export default function () { return 100 }

Then we should import it by writing:

import foo from './foo';

For CommonJS modules, we can write:

foo.js

module.exports = function () { return 100 }

Then we can import it by writing:

const foo = require('./foo');

Repeated Imports and Exports

We can only have one default export in each module.

For instance, we can’t write:

export default class Foo { /*...*/ } 
export default class Bar { /*...*/ }

We have to remove one of them.

If we remove one:

export default class Foo { /*...*/ }

Then we can write:

import Foo from './foo';

Export Statements that Come Before Other Statements

We shouldn’t have export statements that come before other statements.

For instance, we don’t want to fix statements like:

const bool = true
export default bool
const str = 'foo'

Moving all exports to the bottom would make it easier to read.

Use of File Extension within the Import Path

When we write imports, we don’t need an extension for JavaScript files.

For instance, instead of writing:

import bar from './foo/bar.js';

We write:

import bar from './foo/bar';

However, we should put the extension for JSON import.

For instance, we can write:

import bar from './bar.json';

We may also do the same thing for JavaScript files that don’t have the .js extension.

For instance, we can write:

import Component from './Component.jsx';

for JSX files.

Putting Imports First

We should put import statements first.

For instance, we should put them at the top.

Instead of writing:

import foo from './foo'
doSomething(foo)
import bar from './bar'

We write:

import foo from './foo';  
import bar from './bar';
doSomething(foo);

Grouping Exports

We can group exports together to make finding them easier.

For instance, we can write:

const first = 'foo';  
const second = 'bar';
export {  
  first,  
  second,  
}

With CommonJS modules, we can write:

const test = {};  
test.foo = true  
test.bar  = true
module.exports = test;

We also grouped the exports together.

Named Exports

We can import named module members in various ways.

Given that we have:

export const foo = "foo"

We can write:

import { foo } from './foo'

Also, we can write:

export { foo as bar } from './foo'

to export it as bar .

We can also import it as bar:

import { foo as bar } from './foo'

Newline After Import

After a group of imports, we can put a new line to separate the imports from the rest of the code.

For instance, we can write:

import defaultExport from './foo'  
import { bar } from 'bar'  
  
const foo = 'bar';

or:

const foo = require('./foo')  
const bar = require('./bar')  
  
const baz = 1;

for CommonJS modules.

No Absolute Paths

We shouldn’t use absolute paths for imports because it’ll only work on the current computer’s current folder strucutre.

If we move it anywhere, it won’t work.

So we shouldn’t write:

import f from '/foo';  
import bar from '/some/path';

or:

const f = require('/foo');  
const bar = require('/some/path');

Instead, we write:

import f from './foo';  
import bar from './some/path';

or:

const f = require('./foo');  
const bar = require('./some/path');

Conclusion

We should write our imports and exports properly.

Never import with absolute paths.

And we should group them together.

Identifier lengths shouldn’t be too long or short.

Categories
JavaScript JavaScript Best Practices

More JavaScript Habits we can Follow

To make code easy to read and maintain, we should follow some best practices.

In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.

No Reassigning Exceptions in catch clauses

We shouldn’t reassign the error object in the catch clause.

Instead, we should assign it to a new variable to ensure that we don’t lose any information.

For instance, instead of writing:

try {
  // ..
} catch (e) {
  e = 10;
}

We write:

try {
  // ...
} catch (e) {
  const foo = 10;
}

No Unnecessary Boolean Casts

If we already have a boolean variable, then e don’t need to cast it again.

For instance, instead of writing:

var foo = !!!bar;

var foo = !!bar ? baz : bat;

var foo = Boolean(!!bar);

var foo = new Boolean(!!bar);

We write:

var foo = !bar;

var foo = bar ? baz : bat;

var foo = Boolean(bar);

var foo = new Boolean(bar);

Boolean and !! already does the casting so we don’t have to do it again.

No Innecessary Parentheses

We shouldn’t have extra parentheses in our code.

For instance, instead of writing:

a = (b * c);

(a * b) + c;

We write:

a = b * c;

a * b + c;

We skip them to save some typing and make them easier to read.

No Unnecessary Semicolons

We shouldn’t have more semicolons than it’s necessary.

For example, instead of writing:

var x = 10;;

function foo() {
  // code
};

We write:

var x = 10;

function foo() {
    // code
}

No Reassigning Function Declarations

We shouldn’t reassign function declarations.

Instead, we assign whatever we want to assign to a new variable.

For instance instead of writing:

function foo() {}
foo = bar;

We write:

var foo = function () {}
foo = bar;

If we create a function, then keep it a function.

No Assignment to Imported Bindings

If we have imported bindings, then we should use it directly or as to rename it.

Otherwise, we assign what we have to a new variable and then work with it.

For instance, we write:

import mod from "./mod"

mod.prop = 1;

And not:

import mod from "./mod"

mod = 1;

No Variable or Function Declarations in Nested Blocks

We shouldn’t have function declarations in nested blocks.

It’s invalid syntax even though it’s accepted.

For instance, instead of writing:

if (test) {
    function doWork () { }
}

We write:

function doWork () { }

We can also write nested declarations:

function doSomething() {
  function doAnotherThing() {}
}

Conclusion

We shouldn’t use invalid syntax.

Also, redundant code is bad.

Extra parentheses should be removed to save us typing and space.