Categories
JavaScript Best Practices

JavaScript Best Practices for Writing More Robust Code — Checking for Unexpected Values

JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.

In this article, we’ll look at ways to check for unexpected values, including null and NaN .

Checking for null

null is also a value that we may unexpectedly encounter, so we should also check for that.

Checking for null is a bit tricky since we can’t use the typeof operator to check for null as typeof null returns 'object' .

However, we can still use the === operator or the Object.is method to check for null .

We can use the === operator to check for null as follows:

if (foo === null) {  
  //...  
}

In the code above, we just use the === operator to check for null as we would do for any other value.

The === operator doesn’t do any data type coercion, so it’ll compare the value as-is with any data type conversions before doing the comparison.

Therefore, the code above will work for null comparisons since it doesn’t try to convert null to anything else before doing the comparison.

Object.is is a static object method that takes 2 arguments that take 2 objects that are to be compared.

It’ll return true is both arguments are null , so we can use that for checking if something is null .

To check for null with Object.is , we can write the following code:

if (Object.is(foo, null)) {  
  //...  
}

In the code above, we called Object.is with foo and null . Then if foo is null , Object.is will return true .

Check if a Value is NaN

NaN is a value that we’ll encounter if we try to convert something that’s not a number into a number or if we try to divide 0 or a non-number by 0.

There’re many ways to check for NaN , including the isNaN function, the Number.isNaN method, and Object.is .

The === and == operators won’t work because NaN is considered to be different from itself if we use these operators. Therefore NaN === NaN and NaN == NaN both return false .

However, there’re still many options to check for NaN .

The globalisNaN function can be used to check if a value is NaN or not. Data type coercion is done before checking for NaN with this function.

If we pass in something that will be NaN if we convert it to a number, then isNaN will return true . Otherwise, it’ll return false .

For instance, if we have:

isNaN(NaN);         
isNaN(undefined);  
isNaN({});

then they all return true since they all return NaN if we try to convert them to a number.

On the other hand, if we have:

isNaN(true);        
isNaN(null);

These will return true since true coerces to 1 and null coerces to 0 before being compared with isNaN to check if it’s NaN .

Also, the following returns true :

isNaN('456ABC');

since parseInt(‘456ABC’); returns 456, but Number('456ABC') returns NaN .

The Number.isNaN function checks if a value is NaN but doesn’t try to convert it to a number before doing the comparison. This method is new to ES2015.

For instance, we can use that for comparing value as follows:

Number.isNaN(NaN);          
Number.isNaN(Number.NaN);   
Number.isNaN('foo' / 0);  
Number.isNaN(0 / 0);

They all return true since all the expressions that we put into the argument are evaluated to NaN .

Anything that isn’t NaN will return false , so expressions like:

Number.isNaN('foo');

will return false in addition to numbers in the argument. It only checks if the value is NaN without trying to convert a number first.

Likewise, we can use the Object.is method to check if a value is NaN . Like Number.isNaN , it won’t try to do any data type coercion before doing the equality comparison with NaN .

Object.is considers NaN to be equal to itself, so we can use it to check for NaN .

Therefore, we can use it as we do with isNaN . For instance, we can write:

Object.is(NaN, NaN);  
Object.is`(Number.NaN, NaN);` Object.is`('foo' / 0, NaN);  
`Object.is`(0 / 0, NaN);`

will all return true . Anything that isn’t explicitly evaluated as NaN will returns false when comparing against NaN will Object.is . For instance:

Number.isNaN('foo');

returns false .

Conclusion

Checking for null and NaN have their own tricks. We can use === to check for null , in addition to Object.is .

To check for NaN , we can’t use === to check for NaN as NaN === NaN returns false . However, we can use Object.is , isNaN or Number.isNaN to do the comparison.

Categories
JavaScript Best Practices

JavaScript Best Practices — Avoid Variables Bad Practices

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 how to avoid some bad practices when declaring variables.

Don’t Chain Variable Assignments

Variable assignments shouldn’t be chained because we create global variables in some of the variables in the chain.

For instance, if we write the following code to declare multiple variables in a chain as follows:

{
  let a = b = c = 5;
}

Then a would be declared as a block-scoped variable with let . However, the let keyword doesn’t apply to b and c .

They’re all declared as global variables. This is definitely something that we don’t want.

Therefore, we should avoid the chain of assignments that we have above. Instead, we should write to them all in their own line as follows:

{
  let a = 5
  let b = a;
  let c = a;
}

In the code above, we declared the variable a in the same way, we did in the previous example, but we put the declarations of b and c into their own line.

We assigned the value of a to b and also to c . This way, they’re all block-scoped and we won’t be declaring global variables accidentally.

Avoid Using Unary Increments and Decrements (++, --)

We should avoid unary increment and decrement statements since they’re subject to automatic semicolon insertion, which we don’t want since semicolons may be added to places that we don’t expect them to.

Not using increment and decrement operators also prevents us from incrementing and decrementing values unintentionally which causes unexpected behaviors in our programs.

Therefore, if we have the following code:

let num = 1;
num++;

Then should change it to the following:

let num = 1;
num += 1;

This is better since it’s a statement rather than an expression, so we can’t do something like:

let num = 1;
const foo = num++;

foo is still 1 since the latest value isn’t returned if ++ or -- comes after the variable.

We wouldn’t be able to do the same thing with:

num += 1;

so it’s a lot safer since it’s harder to do an assignment with the line above without creating a new line.

Avoid Linebreaks Before or After = in an Assignment. If the Expression We’re Assigning is Long, Surround Them in Parentheses

If we want to assign a long JavaScript expression to a variable, then we should wrap them in parentheses instead of using line breaks. Line breaks aren’t as clear as parentheses in delimiting expressions.

For instance, instead of writing the following:

let str =
  'The quick brown fox jumps over the lazy dog';

We should instead write:

let str = (
  'The quick brown fox jumps over the lazy dog'
);

This way, we make our code clear that the long string is one expression.

No Unused Variables

Unused variables are dead code and dead code shouldn’t be in our production code.

Since it’s unused then they should be removed. They take up space and confuse readers.

Therefore, instead of writing:

let unusedVar = 1;

We should remove it.

var Declarations Get Hoisted

var declarations are hoisted to the top of their closest enclosing function scope, but their assignment isn’t.

This is something that many developers don’t expect since they don’t have the complete understanding of var .

For instance, if we have the following code:

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

foo();

Then x is undefined in the first console log but it’s 1 in the second. If we log it before foo is declared then we get the ‘Uncaught ReferenceError: x is not defined’ error and the function won’t run.

Therefore, the declaration is hoisted onto the top of the function but the value isn’t.

This is an annoying feature of JavaScript which tricks a lot of people. It’s not all that useful, so let and const declarations don’t have this characteristic.

It’s one more reason that we should use let and const instead of var .

Conclusion

var declarations are tricky, so they shouldn’t be used. Dead code like unused variables should be removed.

Variable assignment chains are also tricky since the middleware variables are all declared as global variables, so we should assign them all in their own line.

Finally, increment and decrement operators shouldn’t be used since they both return the new value if it comes before the operand and does the assignment. It’s also subject to automatic semicolon insertion, which does things that we may not expect.

Categories
JavaScript Best Practices

JavaScript Best Practices for Writing More Robust Code — Arrays and Iteration

JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.

In this article, we’ll look at better ways to manipulate arrays and looping through them.

Use the for…of Loop

The for...of loop is a loop that’s introduced with ES2015 to iterate through each entry of an iterable object.

This loop is the best loop for looping through all entries of an iterable object because it works with any kinds of iterable objects, including arrays, the arguments object, maps, sets, and DOM Node lists.

It’s much better than the regular for loop and the while loop because we don’t have to worry about setting the indexes and loop conditions.

All we have to do is to use the for...of loop and reference the object that we want to loop through.

For instance, we can use it to loop through an array as follows:

const arr = [1, 2, 3];
for (const a of arr) {
  console.log(a);
}

In the code above, we used the for...of loop on the arr array to loop through all the entries of arr .

Another good thing about using for...of is that we can use const to make sure that we can’t change the entry that’s being looped through, which is a .

This is a feature that isn’t available with any other kinds of loops.

We can also loop through other iterable objects like maps as follows:

const map = new Map([
  ['a', 1],
  ['b', 2]
]);
for (const [key, value] of map) {
  console.log(key, value);
}

In the code above, we created a new Map instance. Then we can loop through the map object and extract the key and value with the destructuring syntax as we did above.

The for...of loop is the only kind of JavaScript loop that lets us destructure items right inside the loop.

The destructuring syntax lets us extract the items easily and clearly. Therefore, it’s less error-prone than regular for or while loops as we can do a lot all in one line while retaining the clarity of our code.

Use Array.isArray() to Check If a Variable is an Array

Array.isArray() is the most reliable method to check if a variable or a value is an array.

It’s the most reliable method to determine if something is an array because it works for arrays from different iframes or document objects.

We should use this instead of alternatives like instanceof because of the possibility of having multiple global objects existing.

Multiple iframes and tabs will have multiple Array objects, and their Array.prototype property will all be different. To make sure that we check through all of them, we have to use Array.isArray instead of arr instanceof Array .

Checking the constructor property has the same problem as the instanceof check.

Therefore, we should use Array.isArray to check if a value or variable is an array since it checks all global Array objects to see if it’s an instance of them.

For instance, we can use it as follows:

const foo = [1, 2, 3];
const isArray = Array.isArray(foo);

In the code above, we just called Array.isArray on foo , which returns true if foo is an array and false otherwise.

Therefore, isArray should be true since foo is an array.

Photo by Dušan Smetana on Unsplash

Array Instance’s Map Method

Array instance methods are there for a good reason. They are very useful for manipulating the array instance or returning something derived from the array instance.

The map method lets us convert all the values of the array instance and return a new array with all the existing array instance’s values converted with the callback function that we pass into the map method.

Using map is better than using loops and pushing entries to a new array for example since we write less code to do the same thing.

Therefore, there’s no reason not to use a cleaner way with map than using loops.

For example, we can use it as follows:

const arr = [1, 2, 3];
const doubled = arr.map(x => x * 2);

In the code above, we called map on arr with the callback x => x * 2 to double every entry of arr , put them all in a new array in the same order, and return it.

Therefore, doubled is:

[
  2,
  4,
  6
]

Conclusion

To write robust code that deals with arrays, we should use the for...of loop to loop through all entries of an iterable object.

This way, we don’t have to deal with indexes and loop conditions, and it works with all iterable objects.

Also, the destructuring syntax works with it.

The most reliable way to check if a variable or a value is an array is the Array.isArray method since it works for situations where multiple versions of a global object exist when dealing with iframes.

Finally, the array instance’s map method is the best way to convert all values of an original array to new ones by returning the new one.

Categories
JavaScript Best Practices

JavaScript Best Practices for Writing More Robust Code — Checking Undefined

JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.

In this article, we’ll look at ways to check for undefined and the existence of properties to prevent our JavaScript program from crashing.

Checking for undefined with the typeof Operator

undefined is a value that we often encounter by methods that return undefined or by trying to use properties that don’t exist. Therefore, we should check if some variable is undefined before doing our action.

We can either check for undefined by using the typeof operator or using the === operator.

For instance, we can do that with the typeof operator as follows:

if (typeof foo === 'undefined') {
  //...
}

In the code above, we check if foo is undefined by using the typeof operator on foo and see if it returns 'undefined' .

If it is, then we do something. We can also run something if foo isn’t undefined by writing:

if (typeof foo !== 'undefined') {
  //...
}

This is important because trying to do any operation to something that’s undefined will crash our JavaScript app.

Also, it’s important to check if the property exists by checking whether it’s undefined or not. A property exists if it’s not undefined.

For checking object if an object property exists, we can also use the hasOwnPropety to see if a property exists as a non-inherited property.

We can check if a property exists in an object as follows:

if (typeof foo.bar !== 'undefined' &&
  typeof foo.bar.baz !== 'undefined') {
  //...
}

In the code above, we check if foo.bar exists and if foo.bar.baz exists by checking if both of them aren’t undefined . If the first one isn’t then, we know foo.bar exists, then we can proceed to check if foo.bar.baz exists.

We can’t jump straight into the 2nd expression and just write typeof foo.bar.baz !== ‘undefined’ since foo.bar may not exist. Therefore, it may be undefined , so we must also check if foo.bar exists before doing the 2nd check.

This is critical if we want to do some operation to foo.bar.baz since these properties may not exist.

Object.prototype.hasOwnProperty

To check if a property exists as a non-inherited property in an object, we can also use the hasOwnProperty method in the object instance.

For instance, we can rewrite our property check as follows:

if (foo.hasOwnProperty('bar') &&
  foo.bar.hasOwnProperty('baz')) {
  //...
}

In the code above, we checked is foo.bar exists as a non-inherited property with foo.hasOwnProperty(‘bar’) . Then if foo.bar exists, we check if foo.bar.baz exists by writing foo.bar.hasOwnProperty(‘baz’).

However, if the property is set explicitly to undefined , hasOwnProperty still returns true , so if we probably still need to check if the property is set explicitly set to undefined even if we use hasOwnProperty.

Therefore, typeof is probably more reliable for checking for undefined since it works whether undefined is implicit, which is when the property doesn’t exist, or when it does exist and set to undefined explicitly.

=== Operator

We can also just use the === operator to check for undefined . For instance, we can just do a direct comparison with the === operator to check for undefined as follows:

if (foo.bar !== undefined) {
  //...
}

The code above also works since === doesn’t do any data type coercion before doing any comparison.

Object.is

Lastly, we can use the Object.is method to check for undefined . It takes 2 arguments, which are the items that we want to compare.

Object.is different from === as === +0 and -0 are considered different in Object.is and which isn’t the case with === . Also, NaN is considered the same as itself with Object.is.

However, for comparing undefined , there’s no difference between Object.is and ===.

For instance, we can use Object.is as follows to check for undefined:

if (Object.is(foo.bar, undefined)) {
  //...
}

The code above checks if foo.bar is undefined or if foo.bar exists as we did with the === operator.

Conclusion

There’re many ways to check if something is undefined in JavaScript. One way is to use the typeof operator to check if something has type 'undefined'.

Also, we can use the === operator to directly compare if something is undefined . Likewise, we can use the Object.is to check for undefined.

To check if a property exists in an object, we can use the object instance’s hasOwnProperty method. However, this doesn’t work if the property is set explicitly to undefined since it exists and it’s set to undefined.

Categories
JavaScript Best Practices

JavaScript Best Practices for Writing More Robust Code — More Ways to Find Items

JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.

In this article, we’ll look at ways to find items in JavaScript arrays.

Finding If Something Exists in an Array Instance With the some Method

The JavaScript some method lets us add a check if one or more items with the given condition exists in the array instance.

It takes a callback with that has the array entry as a parameter and returns the condition of the item that we’re looking for.

For instance, if we want to check if one more entry in the array instance is even, we use some to do that as follows:

const arr = [1, 2, 3];
const result = arr.some(a => a % 2 === 0);

In the code above, we have the arr array, which has one even number which is 2.

Then we called some on it with the callback a => a % 2 === 0 to check if each entry is even, where a is the array entry that’s being checked.

In this case, if some finds an array entry that’s even, which there is, then it returns true . Otherwise, it returns false .

Therefore, some should return true .

The callback can also take the index of the array entry that’s being checked as the 2nd parameter, and the array that’s being run on in as the 3rd parameter. They’re both optional.

Therefore, we can rewrite our example as follows:

const arr = [1, 2, 3];
const result = arr.some((a, index, array) => array[index] % 2 === 0);

And we get the same result as before.

some can optionally take a 2nd argument, which is the value of this that we want to reference in our callback function.

We can pass in our own value of this as follows:

const arr = [1, 2, 3];
const result = arr.some(function(a) {
  return a > this.min;
}, {
  min: 1
});

In the code above, we pass in a 2nd argument, which is the object { min: 1 } .

Then that’ll be the value of this in our callback, so we can use its min property to check if there’re some entries of the array that’s bigger than 1.

Since we also use this in the callback, we have to use a traditional function to reference the value of this .

Then result should be true since there are entries in arr that’s bigger than 1.

This is more robust than looping through the array ourselves and checking for each entry with a loop as it’s well tested and used frequently, so the possibility of any bugs with this method is almost zero.

Photo by Ramesh Casper on Unsplash

find

The array instance’s find method lets us find the first entry in the array that meets the given condition.

It always searches from the start to the end of the array. find takes callback with the array entry as the first parameter of the callback and returns the condition of the array entry that we’re looking for in the array instance.

For instance, we can use it as follows:

const arr = [1, 2, 3];
const result = arr.find(a => a > 1);

In the code above, we have the find method which takes a callback a => a > 1 to find the first item in arr that’s bigger than 1.

a is the array entry that’s being looped through.

Then we should get 2 returned since that’s the first entry in arr from the start that’s bigger than 1.

The callback can also take an index of the array instance that’s being looped through as the 2nd parameter and the array instance as the 3rd parameter. However, they’re both optional.

We can use them as follows:

const arr = [1, 2, 3];
const result = arr.find((a, index, array) => array[index] > 1);

In the code above, we retrieved the entry being checked by using the index to access the array entry instead of getting it from the parameter itself.

So we should get the same result as before.

Like some , the 2nd argument of the find method is the value of this that we want to reference in our callback.

For instance, we can pass in an object and set it as the value of this in the callback as follows:

const arr = [1, 2, 3];
const result = arr.find(function(a) {
  return a > this.min
}, {
  min: 1
});

In the code above, we passed in { min: 1 } as the 2nd argument of find . Then we accessed the min property of the object in the callback by referencing this.min .

Therefore, we should see the 2 as the value of result since this.min is 1 and we’re checking a to see if it’s bigger than 1.

Again, this is an array instance method, so it’s less likely there’re bugs in the find method than writing our code if we want to find an item in an array.

Conclusion

The array instance’s some method lets us check if one or more entry of an array has an item with the given condition.

An array’s find method lets us find the first array entry that meets the given condition.