Example of Correct Judgment Method of Data Type in JS

  • 2021-11-13 00:48:52
  • OfStack

Preface to the table of contents Can typeof correctly determine the type? Can instanceof correctly judge the type? Object.prototype.toString.call() constructor Array.isArray() Regular judgment Summarize

Preface

Javascript is a dynamic type language. A variable may go through many functions from declaration to final use, and the data type will also change, so it is particularly important to judge the data type of a variable.

Can typeof correctly determine the type?

typeof is an operator followed by a 1-yuan expression to the right and returns the data type of this expression. The returned results are expressed in the form of strings of this type (all lowercase letters), including the following seven types: number, boolean, symbol, string, object, undefined, function and so on.

Because of historical reasons, typeof null will be equal to object when judging the original type. And for objects (Object) and arrays (Array), they will all be converted to object. Examples are as follows:


    typeof 1 // 'number'
    typeof "1" // 'string'
    typeof null // 'object'
    typeof undefined // 'undefined'
    
    typeof [] // 'object'
    typeof {} // 'object'
    typeof function() {} // 'function'

Therefore, we can find that typeof can judge basic data types, but it is difficult to judge complex data types other than functions. So we can use the second method, which is usually used to judge complex data types, and can also be used to judge basic data types.

For a return value of object, there are three scenarios:

The value is null The value is object The value is array

For null, we can use = = = to judge directly. What about arrays and objects? No hurry, let's go on.

Can instanceof correctly judge the type?

instanceof is used to judge whether A is an instance of B. The expression is A instanceof B. If A is an instance of B, true is returned, otherwise false is returned.

instanceof is judged by prototype chain, but for objects, Array will also be converted to Object, and the basic types string and boolean cannot be distinguished. You can put the content you want to judge on the left and the type on the right to judge the JS type, which can only be used to judge complex data types, because instanceof is used to detect whether the prototype attribute of the constructor (right) appears on the prototype chain of an instance object (left). For example:


    function Func() {}
    const func = new Func()
    console.log(func instanceof Func) // true
    
    const obj = {}
    const arr = []
    obj instanceof Object // true
    arr instanceof Object // true
    arr instanceof Array // true
    
    const str = "abc"
    const str2 = new String("abc")
    str instanceof String // false
    str2 instanceof String // true

It seems that using instanceof alone will not work, but we have come to the conclusion that we can't distinguish groups from objects with typeof, so we will write a complete judgment logic with instanceof


    function myTypeof(data) {
        const type = typeof data
        if (data === null) {
            return 'null'
        }
        if (type !== 'object') {
            return type
        }
        if (data instanceof Array) {
            return 'array'
        }
        return 'object'
    }

Object.prototype.toString.call()

Above, we implemented version 1 type judgment through typeof and instanceof, so is there any other channel to make our code more concise? The answer is to use Object. prototype. toString. call ().

Each object has one toString () method, which is called automatically when you want to represent an object as a text value or refer to an object as an expected string. By default, every object derived from Object inherits the toString () method. If this method is not overridden in the custom object, toString () returns


    Object.prototype.toString.call(new Date()) // [object Date]
    Object.prototype.toString.call("1") // [object String]
    Object.prototype.toString.call(1) // [object Numer]
    Object.prototype.toString.call(undefined) // [object Undefined]
    Object.prototype.toString.call(null) // [object Null]

Therefore, based on the above knowledge points, we can package the following general type judgment methods:


    function myTypeof(data) {
        var toString = Object.prototype.toString;
        var dataType = data instanceof Element ? "element" : toString.call(data).replace(/\[object\s(.+)\]/, "$1").toLowerCase()
        return dataType
    };

    myTypeof("a") // string
    myTypeof(1) // number
    myTypeof(window) // window
    myTypeof(document.querySelector("h1")) // element

constructor

constructor judgment method is similar to instanceof, but constructor detects Object and instanceof differently, and constructor can also handle the detection of basic data types, not just object types.

Note:

1. null and undefined have no constructor;

2. Use () when judging numbers, such as (123). constructor. If written as 123. constructor, an error will be reported

3. constructor will make an error during class inheritance, because Object is overwritten and the detection result is wrong


    function A() {};
    function B() {};
    A.prototype = new B();
    console.log(A.constructor === B)  // false

    var C = new A();
    console.log(C.constructor === B)  // true
    console.log(C.constructor === A)  // false 

    C.constructor = A;
    console.log(C.constructor === A);  // true
    console.log(C.constructor === B);  // false

Array.isArray()

Array. isArray () is used to determine whether the passed value is 1 Array. If the object is Array, true is returned, otherwise false is returned.


    Array.isArray([1, 2, 3]); // true
    Array.isArray({foo: 123}); // false
    Array.isArray("foobar"); // false
    Array.isArray(undefined); // false

Regular judgment

We can convert the object and array into a string, so that we can make formatting judgments and get the final type.


    function myTypeof(data) {
        const str = JSON.stringify(data)
        if (/^{.*}$/.test(data)) {
            return 'object'
        }
        if (/^\[.*\]$/.test(data)) {
            return 'array'
        }
    }

Summarize


Related articles: