This is the sixth day of my participation in the August More Text Challenge. For details, see the August More Text Challenge

preface

Data types in JavaScript are the basis of learning JavaScript. The previous articles are all about data types. Today, we aim to master data type detection in JavaScript and start our journey of exploration.

What are some ways that JavaScript can detect data types?

Data type detection has the following methods:

  • tyepof [value]: Operator that detects data types
  • [example] instanceof [class]: Checks whether an instance belongs to this class
  • [example].constructor===[class]: that detects instance and class relationships, and thus data types
  • Object.prototype.toString.call([value]): Use the toString method to return a string, such as “[object object]”

In fact, some of the above methods, which are temporarily drawn, are not actually designed to detect data types. Next, we will introduce each of them, whether you are familiar with or not, continue to read, there are certainly different harvest.

typeof

1. Definition: An operator used to detect a data type. The essence is to directly detect the value (binary) of the data type at the bottom of the computer

2, syntax: tyepof [value]

3, return value:

  • The Typeof operator returns a string, so the result of the test is a string
  • String represents the data type corresponding to value, such as “number”, “string”, “Boolean”, “undefined”, “object”, “function”, “symbol”, “Bigint”

Note:

  • NaN/Infinity are both numbers, so the result is “number”.
  • The result returned by typeof is always a string (the string contains the corresponding type), so when two or more typeof checks occur consecutively, the final result will always be “string”. For instance,typeof typeof []The result of that is “string”.
  • typeof function fn() {}And the result is “function”

The return value of typeof in MDN is:

4, advantages: simple to use, can effectively detect the basic data type values and reference data type values

5. Limitations

  • The result of typeof NULL is “object”. Reason: This is a time-old bug. In the original version of JS, the 32-bit system was used. For performance purposes, the type information of variables was stored in low order.
  • We can’t subdivide the object type, typeof normal/array/regular/date, and the result is “object”. In this case, we can’t tell whether the value is normal or array by typeof.

Having said all that, we have a variable x whose data type is currently uncertain, and we need to determine whether or not the variable x is an object, and if so, we need to perform the processing logic. How do we do that?

First try

if (typeof x === "object") {         
    console.log('This is an object.');
}
Copy the code

Is that ok? For those of you who have read the limitations above, you know that this is an imperfect judgment, because typeof null also results in “object”.

So let’s change it to:

if(x ! = =null && typeof x == "object") {         
    console.log('This is an object.');
}
Copy the code

instanceof

1. Definition: Checks whether the current instance belongs to this class. Underlying mechanism: The result is true as long as the current class appears on the prototype chain of the instance

[example] instanceof [class] [example] instanceof [class

Return value: true if it is, false if it is not

4, advantages: can make up for the limitations of Typeof can not subdivide object types. For example, to check whether a value is an array, just see if the return value is true.

let arr = [];
console.log(arr instanceof Array); // => true
console.log(arr instanceof RegExp); // => false
console.log(arr instanceof Object); // => true
Copy the code

5. Limitations

  1. Cannot detect basic data types
  2. Instances of the basic data type cannot be detected based on it
    • Literal creation cannot be detected
    • Constructor can be detected
  3. There is no way to tell if an Object is normal based on the result, because array objects, regular objects, and so on are all instances of Object, so the test result is true
  4. We can arbitrarily modify the orientation of the prototype, so the test results are inaccurate

They are described below;

/ / 1 point
console.log(1 instanceof Array);  // => false

/ / 2 points
var str = Dream Chaser;
var str2 = new String(Dream Chaser);
console.log(str instanceof String); // false
console.log(str2 instanceof String); // true

/ / 3 points
let obj = [];
console.log(obj instanceof Object); // => true

/ / 4 points
function Fn() {
  this.x = 100;
}
Fn.prototype = Object.create(Array.prototype);

let f = new Fn;
console.log(f, f instanceof Array); // {x: 100} true
Copy the code

The instanceof detection mechanism verifies that the prototype of the current class is present on the instance’s __proto__ chain. The result is true as long as the prototype is present on its __proto__ chain

Can we implement an Instanceof ourselves? Why do you think so much? It’s done.

function instance_of(example, classFunc) {
  // Example => classFunc => class
  let classFuncPrototype = classFunc.prototype,
      proto = Object.getPrototypeOf(example); 
  // example.__proto__ IE not supported

  while(true) {
    if(proto === null) {
      // Object.prototype.__proto__ => null
      return false;
    }
    if(proto === classFuncPrototype) {
      // The instance is an instance of the class
      return true;
    }
    proto = Object.getPrototypeOf(proto); }}__proto__ === class. Prototype
let arr = [];
console.log(instance_of(arr, Array)); // => true
console.log(instance_of(arr, RegExp)); // => false
console.log(instance_of(arr, Object)); // => true
Copy the code

constructor

1, define: determine whether the constructor property value of the current instance is an estimated class

[example]. Constructor ===[class]

Return value: true if it is, false if it is not

4. Advantages:

  • It seems to work a little better than Instanceof and can detect basic data types
  • Instance constructor.Is always equal toClass. The prototype. The constructorThis is the current class itself. This assumes that Constructor has not been modified

5. Limitations

  1. Cannot redirect the prototype of the current class, resulting in inaccurate detection results
  2. Failure to add the private constructor attribute to the current instance can also result in inaccurate inspection results
  3. It is very easy to modify, because constructor in JS is not protected and can be modified at will. In this way, the value detected based on constructor is uncertain, although it is not usually used to detect data types.
/ / 1 point
Number.prototype.constructor = 'AA'; // If you add this, it becomes false
let n = 1;
console.log(n.constructor === Number); // false

/ / 2 points
let arr = [];
arr.constructor = Object; // Execute diam and the result below becomes false
console.log(arr.constructor === Array); // false
Copy the code

Object.prototype.toString.call

Described above the data type of the detection method has some deficiencies, here we introduce the Object. The prototype. ToString. Call method can well judge data types, and several methods make up before the problems,

Every reference type has a toString method, and by default, the toString() method is inherited by every Object. If this method is not overridden in a custom object, toString() returns “[object type]”, where type is the type of the object.

const obj = {};
obj.toString() // "[object Object]"
Copy the code

It should be noted that toString only works if this method is not overridden in custom objects. In fact, most reference types such as Array, Date, RegExp, and so on override toString.

So we wrap up the desired effect by calling the unoverridden toString method on the Object prototype directly, using call to change the reference to this.

1, define: find the toString method on object.prototype, call it, and make this refer to the value of the data to be detected based on the call.

2, Grammar:

  • Object.prototype.toString.call([value])
  • ({}).toString.call([value])

Return value: return a string representing the Object, “[Object class of the currently detected instance]”, for example, “[Object Object]”

Returns the results summary: “[object Number/String, Boolean/Null/Undefined Symbol/object/Array/RegExp/Date/Function]”

4. Advantages:

  • Dedicated to the detection of data type method, the regular army, basically no limitations of the data type detection method
  • Based on it can effectively detect any data type value

5. Limitations

  1. Only built-in classes can be detected, not custom classes
  2. Any custom class will return “[Object Object]”

This method is based on JS itself for data detection, so it is a better method to detect data types

Encapsulates the jQuey method for detecting data types

In a real project, if we wanted to encapsulate a universal method for detecting data types, we would use typeof and toString together. The jQuery source code encapsulates a method for detecting data types.

Principle:

  1. Set the mapping table for the data type
  2. For basic data type values, use typeof detection directly. If it is a reference type, use object.prototype. call to detect the type
  3. Reference data type, from the class2Type object, based on the corresponding property name, find the property value, and return
(function () {
  var class2type = {};
  var toString = class2type.toString; // => Object.prototype.toString

  // Set the data type mapping table
  ["Boolean"."Number"."String"."Function"."Array"."Date"."RegExp"."Object"."Error"].forEach(name= > {
    class2type[`[object ${name}] `] = name.toLowerCase();
  });
  // console.log(class2type);
  function toType(obj) {
    if (obj == null) {
      // If null or undefined is passed, the corresponding string is returned
      return obj + "";
    }
    // Basic data types use Typeof detection
    return typeof obj === "object" || typeof obj === "function" ?
      class2type[toString.call(obj)] || "object" :
      typeof obj;
  }
  window.toType = toType; }) ();console.log(toType(1)); //=>"number"
console.log(toType(NaN)); //=>"number"
console.log(toType([])); //=>"array"
console.log(toType(/^\d+$/)); //=>"regexp"
console.log(toType({})); //=>"object"
console.log(toType(null)); //=> "null"
console.log(toType()); //=>"undefined"
Copy the code

Digression: How to accurately determine the data type?

You can use array.isArray.

Array.isArray is a method on the Array constructor that determines whether a value is of type Array

Array.isArray([1.2.3]); // true
Array.isArray(1); // false
Array.isArray('abc'); // false
Copy the code

Of course, this method can only be used to determine whether an array is of any other data type

reference

  • JS data type detection method — typeof
  • JS data type detection in the advantages and disadvantages of four ways
  • Do you really know variables and types
  • A detailed look at the type detection scheme in JavaScript

conclusion

JavaScript type detection methods have their own characteristics, for its usage we do a summary:

  • Basic data types can be usedtypeofThe syntax is simple and easy to use
  • instanceofandconstructorCan be used to detect the specific type of an object, but after modifying the prototype chain, the results will be inaccurate
  • Object.prototype.toString.callIt’s a universal formula, and you can basically test itJavaScriptAll data types in
  • You can use it directlyArray.isArrayTo accurately detect the array

Feel free to correct any mistakes in the comments section, and if this post helped or liked you, feel free to like or follow.