Categories
JavaScript Best Practices

Maintainable JavaScript — with and for Loop

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by looking at various block statements.

The with Statement

The with statement should never be used.

It was used for manipulating objects within its own context by creating a with block.

For instance, we could write:

var book = {
  title: "javascript for beginners",
  author: "james smith"
};

with(book) {
  message = `${title} by ${author}`;
}

to add the message property to book .

However, this isn’t allowed in strict mode because of its confusing scope.

We don’t know for sure from the code whether message is a global variable or a property of book .

The same issue prevents optimizations from being done since JavaScript engines may guess wrong.

Therefore, we should never use this.

It’s also forbidden in all style guides.

Linters can check for this so we won’t write with statements accidentally.

The for Loop

The for loop is one kind of loop in JavaScript that’s inherited from C and Java.

There’s also for for-in and for-of loop that lets us iterate through a property of an object and entries of iterable objects respectively.

For instance, we can write:

const values = [1, 2, 3, 4, 5],
  len = values.length;

for (let i = 0; i < len; i++) {
  console.log(values[i]);
}

We created a for loop to loop through some numbers by defining the values array and setting its length to len to cache it.

There’re 2 ways to change how the loop proceeds.

One if to use the break statement.

break will end the loop and not continue to the next iteration.

For instance, we can write:

const values = [1, 2, 3, 4, 5],
  len = values.length;

for (let i = 0; i < len; i++) {
  if (i === 2) {
    break;
  }
  console.log(values[i]);
}

to end the loop when i is 2.

Another way to change the loop behavior is with the continue keyword.

This lets us skip to the next iteration of the loop.

for instance, we can write:

const values = [1, 2, 3, 4, 5],
  len = values.length;

for (let i = 0; i < len; i++) {
  if (i === 2) {
    continue;
  }
  console.log(values[i]);
}

Then when i is 2, we’ll skip to the next iteration.

Some style guides like Doug Crockford’s style guide forbids the use of continue .

His reason is that it can be written better with conditions.

For instance, instead of writing:

const values = [1, 2, 3, 4, 5],
  len = values.length;

for (let i = 0; i < len; i++) {
  if (i === 2) {
    continue;
  }
  console.log(values[i]);
}

We can write:

const values = [1, 2, 3, 4, 5],
  len = values.length;

for (let i = 0; i < len; i++) {
  if (i !== 2) {
    console.log(values[i]);
  }
}

He says that it’s easier for programmers to understand conditionals than continue .

continue isn’t used very often as a loop control statement, so we can probably live without it and use conditionals.

Conclusion

with statement should never be used. It’s also disabled in strict mode.

Before using the continue keyword in loops, we should think twice.

Categories
JavaScript Best Practices

Maintainable JavaScript — Undefined, Arrays, and Objects

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code with some conventions for undefined .

Undefined

undefined is a value that’s often confused with null .

This is partly because null == undefined returns true .

However, they’re actually very different from each other.

Variables that haven’t been assigned a value have the initial value of undefined .

This means it’s waiting for a real value to be assigned to it.

If we have:

let animal;
console.log(animal === undefined);

Then the console log will log true .

undefined shouldn’t be used much in our code.

But we need to check for them so that we’ll avoid all sorts of runtime errors.

We often get things that are undefined .

Non-existent properties have value undefined .

Parameters that haven’t have an argument passed in for it is also undefined .

If we try to do something to something that’s undefined , then we’ll get an error.

Therefore, we need to check for them.

To check for undefined , we can use the typeof operator.

If something is undefined , typeof will return 'undefined' .

For example, we can write:

let animal;
console.log(typeof animal);

Then we get 'undefined’ logged.

We shouldn’t use it for assignments, but we should check for them.

Object Literals

Object literals is a popular way to create objects with a set of properties.

It’s shorter than using the Object constructor and does the same thing.

Therefore, we should use the object literal notation to create an object.

For example, instead of writing:

let book = new Object();
book.title = "javascript for beginners";
book.author = "jane smith";

We should write:

let book = {
  title: "javascript for beginners",
  author: "jane smith"
}

It’s shorter and cleaner.

We just specify all the properties and values in between the curly braces.

We include the opening curly brace in the first line.

The properties are indented one level.

And the closing brace is in its own line.

Most style guides and linters suggest this format.

Guides like the Google style guide, Airbnb, style guide, ESLint default rules, etc. all look for this style.

Array Literals

Like object literals, we don’t need the Array constructor to create arrays.

Instead, we use the array literal notation.

For instance, instead of writing:

let fruits = new Array("apple", "orange", "grape");
let numbers = new Array(1, 2, 3, 4);

We write:

let fruits = ["apple", "orange", "grape"];
let numbers = [1, 2, 3, 4];

It’s much shorter and does the same thing.

It’s widely used and it’s common in JavaScript.

The Array constructor also has 2 versions.

It returns an array with the arguments if we pass in multiple arguments.

If there’s only one argument and it’s a nonnegative integer, then it creates an array with the number of empty slots as indicated by the argument.

Therefore, it’s another reason to avoid the Array constructor.

Conclusion

We can work with undefined , objects and arrays in better ways.

Literals are better than constructors for arrays and objects.

Categories
JavaScript Best Practices

Maintainable JavaScript — Switch

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by writing switch statements.

The switch Statement

switch statements are useful for doing something after checking for some value.

There are better ways to format swicth statements.

JavaScript switch statements behave differently than other languages.

Any type of value may be used with it.

And any expressions can be used with a valid case .

Other languages require the use of primitive values and constants respectively.

Switch Indentation

Switch statement’s content should be indented.

For instance, we write:

switch (condition) {
  case 1:
    // ...
    break;

  case 2:
    // ...
    break;

  case 3:
    // ...
    break;

  default:
    // ...
}

We indented the case statement and the content inside it.

The indentation is done with 2 spaces.

This makes the content easier to read.

We also have ab extra line before and after each case statement from the second one on.

Doug Crockford’s style guide has another suggestion.

The line between the case statements is removed.

For instance, we can write:

switch (condition) {
  case 1:
    // ...
    break;
  case 2:
    // ...
    break;
  case 3:
    // ...
    break;
  default:
    // ...
}

We remove the blank lines in between the parts of the switch statement.

However, all style guides have the same recommendation for indentation.

Falling Through

Accidentally omitting the break keyword at the end is a common mistake we make when we write switch statements.

This will cause the case statements below them to also run.

Some people suggest that every case should end with break , return or throw without exception.

This way, the case will end where we expect them to end.

If we make it clear in the code that falling through isn’t a mistake, then we can let the case statements fall through.

For example, we can write:

switch (condition) {

  // falls through
  case 1:
  case 2:
    // ...
    break;

  case 3:
    //...
    // falls through
  default:
    // ...
}

so that everyone knows that the fall through is intentional.

The first case falls to the 2nd.

And the 3rd falls to the default case.

They’re all marked with comments to communicate the programmer’s intent.

Some style guides, like Douglas Crockford’s style guide, don’t all fall throughs on switch ever.

But this depends on our team’s preference.

default

Some people also argue whether the default case is required.

Some believe that they should always be included.

It’s more like people follow this pattern.

However, if there’s no default case that we can think of to add, we may omit it.

If we omit the default case, we may communicate that with comments so that everyone knows it’s intentional.

For instance, we can write:

switch (condition) {
  case 1:
    // ...
    break;
  case 2:
    // ...
    break;
  // no default
}

This way, we all know it’s not a mistake.

Conclusion

There’re several things to think about when we write switch statements.

breaks and default cases can be added or not, but we’ve to communicate our intent clearly.

This way, there won’t be any misunderstanding.

Categories
JavaScript Best Practices

Maintainable JavaScript — Numbers and Null

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code with some conventions for numbers and null.

Numbers

There’s only one kind of number in JavaScript.

Integers and floats are stored with the same data type.

There’re various kinds of number literals that we can write.

For instance, we can write:

const count = 10;

to write an integer.

To write decimals, we can write:

let price = 10.0;
var quantity = 10.00;

We can have decimals after the number.

However, we can also write:

const count = 10.;

But this is confusing so we should avoid it.

The hanging decimal is also useless.

We can also have a leading decimal point with our JavaScript numbers:

var price = .2;

But it’s clearer to just put the 0 before the decimal point:

var price = 0.2;

We should never write octal literals since they’re confusing and are deprecated:

var num = 010;

The 0 cause confusion between octal and decimal numbers.

We can also write JavaScript hex numbers:

let num = 0xFF;

to write numbers in scientific notation, we can use the letter e:

var num = 1e20;

1e20 is 100000000000000000000 or 10 ** 20 .

The hanging and leading decimals can easily be confused for mistakes.

They‘re forbidden in many style guides and can be caught with ESLint, JSLint, and JSHint.

Warnings will also be made if octal literals are encountered.

Null

null is often misunderstood and confused with undefined .

We should use undefined most of the time to reduce confusion.

But we can use null in a few cases.

We can use them to initialize a variable that may be assigned with an object later.

Also, we can use it compare against a variable that may be null .

And we can pass that into a function where an object is expected.

We can also return null in place of an object when there’s nothing to return.

But we shouldn’t use null to test whether an argument is supplied.

And we don’t test uninitialized variables for null .

So we can write:

let person = null;

Or we can write:

function createPerson() {
  if (condition) {
    return new Person("nick");
  } else {
    return null;
  }
}

But we shouldn’t use it compare against an uninitialized variable like:

if (person != null) {
  doWork();
}

We also shouldn’t check against null to see if a variable is passed in:`

function doWork(arg1, arg2, arg3, arg4) {
  if (arg4 != null) {
    doSomething();
  }
}

We used != which is bad since it does automatic data type coercion and we check against null when we should be checking against undefined .

This is because if we don’t pass in an argument, then the parameter will be undefined .

null is a placeholder for objects.

It’s not a value to represent nothing.

Conclusion

We should be careful with placing decimal places with numbers.

Also, we shouldn’t use octal literals.

null should only be used in some limited cases.

Categories
JavaScript Best Practices

Maintainable JavaScript — Names

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by improving naming.

Naming

To make our JavaScript code maintainable, we got to make the names descriptive so that we know what they do fro the names.

Also, the case should be consistent so that we won’t be confused with the names.

Variables and function should be camel case,

Camel case means that the name starts with a lower case letter and each subsequent word starts with an uppercase letter.

For instance, these are camel case:

let myName;
const someVariable;
let veryLongName;

They all start with a lower case with subsequent words start with upper case.

Variables and Functions

Variable names are camel case and should start with a noun.

This way, we know what they store.

For example, we can write:

let count = 10;
const firstName = "james";
let isTuesday = true;

to define variables with nouns.

If we define variables with other kinds of words like verbs, then we’ll easily confuse them with functions.

So we shouldn’t define variables with names like:

let getCount = 10;

get implies that we’re doing something so that doesn’t make sense.

However, we should create functions that starts with verbs:

function getCount() {
  return 10;
}

We’re getting some value when we call getCount so it makes sense for the function to start with get .

This also means that our function names shouldn’t look like variable names.

For instance, if we have:

function theCount() {
  return 10;
}

then we’ll easily confuse that with a variable.

Naming is more of an art than a science, but there’re some conventions we can follow.

Words like count , length , and size suggests number.

And words like name and message suggests that it’s a string.

Meaningless names like foo or bar should be avoided.

Some conventions for function names include prefixes like:

  • can to suggest a function that returns a boolean
  • has is a function to return a boolean
  • is is the same as can or has
  • get suggests that a function is returning a non-boolean value
  • set is a function that’s used to save a value

For example, if we have:

if (canSetName()) {
  setName("nick");
}

then we know that if we can set the name, then we set the name.

Another example would be:

if (getName() === "nick") {
  jump();
}

Then we know that we’re getting the name with getName and we’re doing something with jump .

Constants

Before ES6, there’s no concept of constants.

But now, we can define constants with const .

The names for constants should be upper case.

For example, we can write:

const MAX_COUNT = 10;

to let everyone know that MAX_COUNT is a constant.

Constants can’t be reassigned to a new value, but they’re mutable.

Having a separate convention for constants lets us distinguish between variables and constants.

Conclusion

We should follow some conventions for variable and function names and constants.