As an entry level knowledge point of JavaScript, JS data types are particularly important in the whole process of learning JavaScript. Because in JavaScript programming, we often encounter boundary data type condition judgment problems, a lot of code can only be reliably executed under a certain data type

Basic concepts of data types

Data types include undefined, NULL, Boolean, String, Number, Symbol, Biglnt, Object, etc. The first seven types are basic types, and the last one (Object) is reference type, which needs to be paid attention to. Because it is the data type that is used most frequently in daily work and requires the most technical attention. Reference data types (objects) are divided into the common types on graphs: array-array objects, regexp-regular objects, date-date objects, math-math functions, and function-function objects.

The following two points are important to understand here, because the various JavaScript data types end up in different memory after initialization, so the above data types can be roughly divided into two categories for storage:

  • The base type is stored in stack memory, and when referenced or copied, an identical variable is created;
  • Reference types are stored in heap memory and store addresses. Multiple references point to the same address. There is a concept of “sharing” involved.

Js, there are many kinds of methods to detect data types, including typeof, instanceof, Object. The prototype. ToString, below the constructor respectively introduces the several methods

The first judgment method: Typeof

This is one of the more common methods, so let’s quickly review it with a piece of code.

  typeof 1    // 'number'
  typeof '1'  // 'string'
  typeof undefined    // 'undefined'
  typeof true         // 'boolean'
  typeof Symbol(a)// 'symbol'
  typeof null     // 'object'
  typeof []   // 'object'
  typeof {}   // 'object'
  typeof console  // 'object'
  typeof console.log  // 'function'
Copy the code

Pay attention to

  • This method does not mean that null is a reference data type, and null itself is not an object. If null is used in the statement, it can be directly checked by “===null”
  • If you refer to the datatype Object, use typeof. If you refer to the datatype Object, use typeof

The second judgment method: instanceof

With instanceof, we create a new object, and that new object is the object from which it inherits its prototype chain. By instanceof, we can determine whether this object is the object generated by the previous constructor, and thus basically determine the data type of this new object

  let Fn = function() {}
  let gs = new Fn()
  gs instanceof Fn // true
  let gcs = new String('Mercedes Gs')
  gcs instanceof String // true
  let str = 'string'
  str instanceof String // false
Copy the code

You can actually write an Instanceof method yourself

function newInstanceof(val, type) {
    // Use typeof to determine the underlying data type. If so, return false
    if (typeofval ! = ='object' || val === null) return false;
    // getProtypeOf is an Object API that can get the parameters of the prototype Object
    let proto = Object.getPrototypeOf(val);
    while (true) {                  // Loop down until you find the same prototype object
        if (proto === null) return false;
        if (proto === type.prototype) return true;// Find the same prototype object, return true
        proto = Object.getPrototypeof(proto); }}// Verify that the newInstanceof method is valid
console.log(newInstanceof(new Number(123), Number));    // true
console.log(newInstanceof(123.Number));                // false
Copy the code

Pay attention to

  • Instanceof can accurately determine complex reference data types, but not the underlying data types

Neither of the above two methods can be used alone to satisfy the judgment of all scenarios, and only the two methods are mixed. Now let’s look at the third method

The third judgment method: Object. The prototype. ToString

ToString () is an Object prototype method that returns uniformly a string of the format “[Object Xxx]”, where Xxx is the type of the Object. For Object objects, toString() returns [Object Object]; Other objects need to be called by call to return the correct type information. Let’s look at the code first

  Object.prototype.toString({})       // "[object Object]"
  Object.prototype.toString.call({})  // Same result as above, add call also ok
  Object.prototype.toString.call(1)    // "[object Number]"
  Object.prototype.toString.call('1')  // "[object String]"
  Object.prototype.toString.call(true)  // "[object Boolean]"
  Object.prototype.toString.call(function(){})  // "[object Function]"
  Object.prototype.toString.call(null)   //"[object Null]"
  Object.prototype.toString.call(undefined) //"[object Undefined]"
  Object.prototype.toString.call(/123/g)    //"[object RegExp]"
  Object.prototype.toString.call(new Date()) //"[object Date]"
  Object.prototype.toString.call([])       //"[object Array]"
  Object.prototype.toString.call(document)  //"[object HTMLDocument]"
  Object.prototype.toString.call(window)   //"[object Window]"
Copy the code

Pay attention to

  • This method does a good job of determining reference data types, including browser Windows window and Document
  • This method returns a uniform string format of “[object Xxx]”, where the first letter of “Xxx” in the string must be uppercase.

We can encapsulate a utility function to detect data types

function ifType(val){
  let type  = typeof val;
  if(type ! = ="object") {    // Check typeof first, if it is a basic data type, return directly
    return type;
  }
  // If typeof returns object, regex returns result
  return Object.prototype.toString.call(val).replace(/^\[object (\S+)\]$/.'$1');
}
Copy the code

(4) Constructor

Constructor is automatically generated below the stereotype of its corresponding object. When we write a constructor, the program automatically adds: constructor name. Prototype. constructor = constructor name

  var str = 'hello';
  alert(str.constructor == String);//true
  var bool = true;
  alert(bool.constructor == Boolean);//true
  var num = 123;
  alert(num.constructor == Number);//true
  var nul = null;
  alert(nul.constructor == Object);/ / an error
  var und = undefined;
  alert(und.constructor == Object);/ / an error
  var oDate = new Date(a); alert(oDate.constructor ==Date);//true
  var json = {};
  alert(json.constructor == Object);//true
  var arr = [];
  alert(arr.constructor == Array);//true
  var reg = /a/;
  alert(reg.constructor == RegExp);//true
  var fun = function () {}; alert(fun.constructor ==Function);//true
  var error = new Error(a); alert(error.constructor ==Error);//true
Copy the code

! Pay attention to

  • Null and undefined are invalid objects and therefore have no constructor, and these two types of data need to be judged in other ways
  • Constructor is unstable. This is mainly true of custom objects. When developers rewrite Prototype, the original constructor reference is lost and constructor defaults to Object
  • When overriding an object prototype, it is generally necessary to re-assign constructor to ensure that the type of the object instance is not tampered with

conclusion

  • Typeof can determine basic data types except null, and reference data types except function
  • Instanceof can accurately determine complex reference data types, but not the underlying data types
  • Object. The prototype. ToString good reference data types, including browser window, the window and document
  • Constructor is unstable, and when developers rewrite Prototype, the original constructor reference is lost and constructor needs to be reassigned. Not recommended for personal use