DEV Community

John Au-Yeung
John Au-Yeung

Posted on

More JavaScript Mistakes You May be Making

Subscribe to my email list now at http://jauyeung.net/subscribe/

Follow me on Twitter at https://twitter.com/AuMayeung

Many more articles at https://medium.com/@hohanga

JavaScript is a language that’s friendlier than many other programming languages in the world. However, it’s still very easy to make mistakes when writing JavaScript code through misunderstanding or overlooking stuff that we already know. By avoiding some of the mistakes below, we can make our lives easier by preventing bugs and typos in our code that bog us down with unexpected results.


Confusing Undefined and Null

JavaScript has both undefined and null for non-values. However, there are quite a few differences between the two. undefined means that the variable may have been declared, but nothing is set to it. A variable can also be explicitly set as undefined. The type of an undefined variable, when checking the type with the typeof operator, will get us the type 'undefined'. Functions that don’t return anything returns undefined. On the other hand, null values have to be explicitly set by functions that return null or just set directly to a variable. When we check an object that has the null value set, we’ll find that the type of it is'object' if a variable has the null value.

For this reason, it’s probably easier to stick to undefined whenever we can when we’re setting variable values to non-values. It reduces confusion and we only have to check that the type of a variable is 'undefined' to see whether it’s undefined. That’s less painful than having two checks, for both null and undefined.

To write functions that return undefined, we don’t have to do anything like the following example:

const f = () => {}

To set a variable that was assigned some other value to undefined, we can write:

x = undefined;

To check if a property value is undefine, we can write:

typeof obj.prop === 'undefined'

or

obj.prop === undefined

To check if a variable is undefined, we can write the following code:

typeof x === 'undefined'

A declared variable that hasn’t been assigned anything automatically has the value undefined.

If we have to check for null, then we can write:

obj.prop === null

or

x === null

for variables. We can’t use the typeof operator for checking null because the data type of null is 'object'.

Photo by Mikhail Vasilyev on Unsplash


Confusing Addition and Concatenation

In JavaScript, the + operator is used for both adding two numbers and concatenating strings together. Because JavaScript is a dynamic language, the operands are all automatically converted to the same type before the operation is applied. For example, if we have:

let x = 1 + 1;

then we get two because they’re both numbers. The + operation was used for addition like we expected. However, if we have the following expression:

let x = 1 + '1';

then we get '11' because the first operand was coerced into a string before the + operation is applied. The + operation was used for concatenation instead of addition. When we use the + operator on multiple variables, this makes knowing the type even harder. For example, if we have:

let x = 1;  
let y = 2;  
let z = x + y;

as we expect, we get three because x and y are both numbers. On the other hand, if we have:

let x = 1;  
let y = '2';  
let z = x + y;

then we get '12' because y is a string, so the + operator was used for concatenation instead. To solve this issue, we should convert all the operands to numbers first before using them with the + operator. For example, we should rewrite the above example into the following:

let x = 1;  
let y = '2';  
let z = Number(x) + Number(y);

The code above will get us 3 as the value of z since we converted them both to numbers with the Number factory function first. The Number function takes in any object and returns a number if it can be parsed into a number, or NaN otherwise. An alternative way to do this is to use the new Number(...).valueOf() function, as we do in the following code:

let x = 1;  
let y = '2';  
let z = new Number(x).valueOf() + new Number(y).valueOf();

Since new Number(...) is a constructor that creates an object type, we want to use the valueOf function to convert it back to a primitive type to make sure that what we get is a number type. A shorter way to do this is to write:

let x = 1;  
let y = '2';  
let z = +x + +y;

The + sign in front of a single operand will try to convert the single operand into a number or toNaN if it can’t be converted into a number. It does the same thing as the Number function. We can also convert a variable to a particular type of number. The Number object has a parseInt function to convert a string or object into an integer and a parseFloat function to convert a string or object into a floating-point number. parseInt takes the object you want to convert to a number as the first argument. It also takes a radix as an optional second argument, which is the base of the mathematical numeral systems. If the string starts with 0x, then the radix will be set to 16. If the string starts with anything else, then the radix will be set to 10.

We can use them as in the following examples:

let x = 1;  
let y = '2';  
let z = Number.parseInt(x) + Number.parseInt(y)

Also, we can use the parseFloat function as in the following code:

let x = 1;  
let y = '2';  
let z = Number.parseFloat(x) + Number.parseFloat(y)

We will get 3 in both of the examples above.


Breaking Return Statements Into Multiple Lines

JavaScript closes a statement at the end, so one line code is considered distinct from the other. For example, if we have:

const add = (a, b) => {  
  return  
  a + b;  
}

we get undefined if we run console.log(add(1, 2)); since we ran the return statement, which ended the function execution, before a + b is run. Therefore, a + b will never be run in this function. To fix this, we either have to put the return statement all in one line or use parentheses to surround what we want to return. For example, we can write:

const add = (a, b) => {  
  return a + b;  
}

This will log 3 if we run console.log(add(1, 2)); since we are actually returning the computed result in the function. We can also write:

const add = (a, b) => {  
  return (  
    a + b  
  );  
}

This is handy for returning expressions that might be longer than one line. This will also log 3 if we run console.log(add(1, 2));. For arrow functions, we can also write:

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

for single-line functions since the return statement is implicit for single-line arrow functions. We can also write:

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

to get the same thing. This also works for single-line arrow functions.

In JavaScript, if a statement is incomplete, like the first line of:

const power = (a) => {  
  const  
    power = 10;  
  return a ** 10;  
}

inside the function then the JavaScript interpreter will run the first line together with the second line to get the full statement. So:

const  
  power = 10;

is the same as:

const power = 10;

However, for complete statements like return statements, the JavaScript interpreter will treat them as separate lines. So:

return   
  a ** 10;

is not the same as:

return a ** 10;

Even though JavaScript is a friendly language, it’s still very easy to make mistakes when writing JavaScript code. It’s easy to confuse undefined and null when we aren’t familiar with JavaScript. Because of the dynamic typing nature of JavaScript, operators like the + operator that can do multiple things can easily be converted to a type we don’t expect and produce the wrong result. Also, if statements can be complete on their own, then they shouldn’t be written in their own lines if we want both lines to be together.

Top comments (11)

Collapse
 
kimsean profile image
thedevkim

its also possible to check the value if its null or undefined with this.

value ? 'has value' : 'undefined or null'
Collapse
 
aumayeung profile image
John Au-Yeung

This wouldn't be 100 percent reliable since 0, empty string, and NaN are also falsy.

So you would get the second choice returned in those cases as well.

Collapse
 
kimsean profile image
thedevkim • Edited

Yea, i guess you could just use the snippet if you wanted to check if theres really a value or not. I think it could be useful sometimes when you are getting a value from an api and you don't have access into the backend funtions, and they just throw either undefined null 0 or empty string

Thread Thread
 
fref profile image
Fredrik Fall

My view is to have undefined something only the runtime is allowed to set, while null is something I deliberately set.
This way you get a hint who messed up if the value is missing.

Thread Thread
 
aumayeung profile image
John Au-Yeung

As long as we remember the difference, I think it's OK. Also, we have to be consistent in how we use them.

Collapse
 
fref profile image
Fredrik Fall

Nice article!

To add to the part about addition/concatenation, the underlying problem
is javascript's automatic type-convertions. The basis for the infamous "WAT" video on youtube (recommended).

String concatenation is also being replaced by template literals for projects employing the newer ES versions.

Collapse
 
aumayeung profile image
John Au-Yeung

Yea. Type coercion is tricky. I think we just have to convert everything to the same type so that we won't make mistakes with we apply operators to them.

Collapse
 
diek profile image
diek

I saw an interview when the code they were asking to explain, has the broken line return. That was an unexpected behavior at first look.

Collapse
 
aumayeung profile image
John Au-Yeung

Breaking return statement is most likely a mistake since the code below is unreachable since the function already stopped running after the return line.

Collapse
 
diek profile image
diek

I know, but at first look can be confusing. It is obvious when you know it, like the comparation with coercion types xD

Collapse
 
zorianiysapfir profile image
Info Comment hidden by post author - thread only accessible via permalink
Yaroslav Pidmohylniy

OMG, pretty useless article. Just read "You do not know JS" and that is all.

Some comments have been hidden by the post's author - find out more