Who hasn’t been victimized by an object type error in a front-end project?

The typeof operator

Obtain the typeof the operand through the typeof operator:

  typeof undefined; // undefined
  typeof []; // object
  typeof '123'; // string
Copy the code

There are two things to remember about the Typeof operator. The first is when the operand is null.

  typeof null; // object
Copy the code

Point two: This works well when the operands are Primitive, but a determination of the specific type of the object is often not the result we need.

Null, Undefined, String, Number, Boolean, and Symbol.

  typeof '123'; // string
  typeof new String('123'); // object
Copy the code

When we first started learning javascript, we often heard that “everything in JS is an object”. In fact, the Primitive Value does not contain the Primitive Value.

The instanceof operator

The instanceof operator is used to check whether the constructor stereotype is in the stereotype chain of the object.

  const s = new String('123');

  s instanceof String; // true
  s instanceof Object; // true
Copy the code

Now let’s do something:

  s.__proto__ = Object.prototype;

  s instanceof String; // false
  s instanceof Object; // true
Copy the code

Using the instanceof operator, we can determine the value of a custom object:

  function Animal (name) {
    this.name = name
  }

  const fizz = new Animal('fizz');

  fizz instanceof Animal // true
Copy the code

The constructor property

In fact, we can also achieve the effect of type judgment using the constructor attribute:

  fizz.constructor === Animal // true
Copy the code

In real life, however, the constructor property can be modified at will, and it’s easy to overlook constructor’s correct orientation in stereotype inheritance:

  function Rabbit (name) {
    Animal.call(this, name)
  }

  Rabbit.prototype = Object.create(Animal.prototype);
  // You need to manually set the correct orientation for constructor
  Rabbit.prototype.constructor = Rabbit;

  const rabbit = new Rabbit('🐰');

  rabbit.constructor === Rabbit // true
Copy the code

As a matter of good programming practice, we should keep the constructor property pointed correctly.

The toString method

The toString method solves almost all of the built-in object types:

  function type (obj) {
    return Reflect.apply(Object.prototype.toString, obj, []).replace(/^\[object\s(\w+)\]$/.'$1').toLowerCase()
  }
  
  type(new String('123')) // string
Copy the code

However, this method is still invalid for custom constructors.

Built-in Symbol interface

ES6 exposes some built-in apis through Symbol:

  Animal.prototype[Symbol.toStringTag] = 'Animal';
  type(rabbit) // animal
Copy the code

Now, we can satisfy all of our requirements with toString, but there is no shortage of superficial programmers:

  const o = {
    get [Symbol.toStringTag] () {
      return 'Array'
    }
  }

  type(o) // array
Copy the code

The exception also exposes Symbol. HasInstance for the instanceof operator, which will not be repeated here.

The pit of those years

Here’s a simple example:

  function test (decimal) {
    if (type(decimal) === 'number') {
      return decimal.toFixed(2)}else if (type(decimal) === 'string') {
      return parseFloat(decimal).toFixed(2)}else {
      return '0.00'
    }
  }

  test(28.39843) / / 28.40
  test('323.2321321') / / 323.23
Copy the code

Anyone who has used the toFixed() method knows that it is a method on number.prototype, and that there are all sorts of problems if you pass in something other than a Number type.

Of course we are in an era of a boom in front-end tools, with many tools for static type checking emerging:

  • Produced by the Flow. Js Facebook
  • TypeScript Microsoft ‘

For those of you who like this article, please follow my subscription account for more content.