← back to the blog


6 JavaScript Quirks that every JS developer should know!

Posted on July 4th, 2020 in JavaScript by George

 

1. typeof null === "object" returns true;

 

Ok, let's assume you have an array of values that have different data types. (string, object, number, etc).

Now you want to filter out the nonsense and only use the valuable data which this time around are the objects in the collection.

 

const importantData = [{name: 'Alan', age: 44}, 'just a string', 44, null, {name: 'Maria', age: 31}];

importantData.map((el)=>{

   // If the data type in the collection is an object that means it must be useful, right?   

  if(typeof el === 'object') {
    console.log('Push this object to useful data', el);
  }
});

 

Guess what gets printed to the console? 

 

Use this object as useful data: { name: 'Alan', age: 44 }
Use this object as useful data: null
Use this object as useful data: { name: 'Maria', age: 31 }

 

You probably have no use of 'null' in your important new data set.

The best workaround this issue is to check against null and against the constructor of the iterated value.

 

const importantData = [{name: 'Alan', age: 44}, 'some strig data', 44, null, {name: 'Maria', age: 31}, false];

importantData.map((el)=>{

   //More accurate check 

  if((el !== null) && (el.constructor === Object)) {
    console.log('Use this object as useful data:', el);
  }
});


//Output 

Use this object as useful data: { name: 'Alan', age: 44 }
Use this object as useful data: { name: 'Maria', age: 31 }



 

2. When setting an object property, JavaScript will implicitly stringify the parameter value  

 

Take this example: 

 

 

let a = {};

let b = { key: 'george' };

let c = { key: 'nina' };

a[b] = 999;
a[c] = 1111;

console.log(a[b]);

 

What is the answer to the console log? If you answer 999, that is wrong. Why?

When setting an object property, JavaScript will implicitly stringify the parameter value. In this case, since "b" and "c" are both objects, they will both be converted to "[object Object]" same as the toString method will be called on them.

 

3. LET and CONST have different rules in regards to the scope in comparison to var.

 

This is self-explanatory but is worth mentioning because I have seen many times people getting errors when using a "for loop" or when they want to declare some function scope inside of an "if-else" statement block.

For example:

 

const what = () => {
  var output = 'George';

  if (output) {
    let output = 'Nina';
  }

  return output;
}

console.log(what());

 

The output is George. Surprised? 

Now let's replace let with var.

 

const what = () => {
  var output = 'George';

  if (output) {
    var output = 'Nina';
  }

  return output;
}

console.log(what());

 

The output is Nina.

In the let example, let output will not redeclare the variable but instead will create a brand new one in the "if" block scope.

 

4. A new line after the return statement will implicitly add a semicolon.

 

function example()
{
  return
  {
      data: "important info"
  };
}

console.log(example());

 

This example will return undefine although you may expect the object to be returned.

 

5. Numbers in JavaScript are all treated with floating point precision

 

You may expect something like 0.1 + 0.2 to equal 0.3 while in fact, the output will be 

0.30000000000000004.

If you encounter some unexpected results in the calculation, make sure you sanitize the output to best suit your needs. Math and Number object have lots of useful methods.

 

6. Method overloading

 

JavaScript has not such a thing as a method overloading, nothing as you see in C# for example.

The closest you can get to this is a workaround convention.

You provide the same number of arguments to the method. The last argument is an object that holds values to be treated as options or conditions.

Based on the options you can instruct the behavior.

Take this example:

 

// Instantiate a class in JS old fashion or usee ES6 class syntax

function ClassWithOverloadedMethod(name, age) {
   this.name = name;
   this.age = age;
}

//Define the method with overloads

ClassWithOverloadedMethod.prototype.overloadedMethod = function (message, options = {}) {
  if(options.withInfo) {
    return `Name: ${this.name}, Age: ${this.age} said: ${message}`;
  } else {
    return message;
  }
}

let newObj = new ClassWithOverloadedMethod('George', 31);


console.log('Call without options: ', newObj.overloadedMethod('Hello there', {}));

console.log('Call with options:', newObj.overloadedMethod('Hello there', {withInfo: true}));

 

Output: 

 

Call without options:  Hello there
Call with options: Name: George, Age: 31 said: Hello there

 

If you have managed to follow so far, Thank You.