数据类型检测

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
</body>

</html>
<script>
    /*
    数据类型检测
        1.typeof用来检测数据类型的运算符
        typeof  [value] => 字符串,包含对应的数据类型
            局限性:
                typeof  null -> "object"
                typeof 检测对象类型值,除了可执行对象{函数}可以检测出来是"function",其余都是"object"
                基于typeof检测一个未声明的变量,结果是"undefined",而不会报错「基于let在后面声明则会报错」
                typeof 检测原始值对应的对象类型的值,结果是字符串"object"
                为啥:typeof检测数据类型是,按照计算机底层存储的二进制值,来进行检测的,它认为以"000"开头的都是对象,而null都是零
            好处:
                简单、性能好 

        2. instanceof临时用来"拉壮丁"检测数据类型,本意是检测当前实例是否属于这个类
            [value] instanceof [Ctor] => true/false
            好处: 细分对象数据类型值「但是不能因为结果是true就说它是标准普通对象』
            弊端:不能检测原始值类型的值『但是原始值对应的对象格式实例则可以检测』;但是因为原型链指向是可以肆意改动的,所以最后检测的结果不一定准确;
            原理:按照原型链检测的;只有当前检测的构造函数(它的原型对象),出现在实例的原型链上,则检测结果就是TRUE;如果找到Object.prototype都没有找到,则结果就是FALSE;
            f instanceof Fn -> Fn[Symbol.hasInstance](f) 新语法规范

        3.constructor 也是"拉壮丁"
        constructor的修改比instanceof更"肆无忌惮"

        4.Object.prototype.toString.call([value]) 这是JS中唯一一个检测数据类型吗没有任何瑕疵的『最准确的,除了性能比typepf略微少那么一丢丢,写起来略微麻烦一点点』
            =>"[object Number/String/Boolean/Null/Undefined/Symbol/BigInt/object/Function/RegExp/Array/Math/GeneratorFunction... (原型是什么类型检测出来是什么 object后面就跟什么)]" 
            大部分内置类的原型上都有toString方法,一般都是转换为字符串的,但是Object.prototype.toString是检测数据类型的,返回值中包含自己所属的构造函数的信息...   

            Object.prototype.toString.call([value])
                1.为啥要用call?
                ([]).toString 调用的是Array.prototype上的toString,是转换为字符串
                ({}).toString 调用的是Object.prototype上的toString,是检测数据类型的『方法中的this是谁,就是检测谁的类型』 —> 我们需要把Object.prototype.toString执行,而且还要改变其中的this
                ->({}).toString.call(10) =>"[object Number]"
                2.检测返回值遵循啥原则?
                    一般都是返回当前实例所属的构造函数类型信息
                    但是如果实例对象拥有 Math[Symbol.toStringTag]="Math"=> Object.prototype.toString.call(Math)=> "[object Math]"

    */

    // 4.Object.prototype.toString.call([value])
    /* class Fn{
        // constructor(){
        //     this[Symbol.toStringTag]="Fn"
        // }
        [Symbol.toStringTag]="Fn";
    }
    let f =new Fn;
    console.log(Object.prototype.toString.call([Fn]));//"[object Function]"
    console.log(Object.prototype.toString.call([f]));//"[object object]" ? */

// GeneratorFunction 生成器函数


    /* // 3.constructor 
    let arr=[],n=10,m=new Number(10);
    console.log(arr.constructor===Array);//=>true
    console.log(arr.constructor===RegExp);//=>false
    console.log(arr.constructor===Object);//=>false  
    // 如果CTOR结果和Object相等,说明可能是标准普通对象
    console.log(n.constructor===Number);//=>true
    console.log(m.constructor===Number);//=>true

    /* function Fn(){}
    let f =new Fn;
    console.log(f.constructor===Fn);//=>true
    console.log(f.constructor===Object);//=>false */
    /*function Fn(){}
    Fn.prototype={};//重新定向后丢失了constructor
    let f =new Fn;
    console.log(f.constructor===Fn);//=>fale
    console.log(f.constructor===Object);//=>ture */


    // 2.instanceof
    /*     let arr=[10,20,30];
        console.log(arr instanceof Array);//=>true
        console.log(arr instanceof RegExp);//=>false
        console.log(arr instanceof Object);//=>true
    
        console.log(new Number(1) instanceof Number);//=>true
        console.log(1 instanceof Number);//=>false */


    /* // class Fn{
 
    // }
    // Fn.prototype=Array.prototype;//不行没有用
    // let f=new Fn;
    // function Fn() {
 
    // }
    // Fn.prototype = Array.prototype;
    // let f = new Fn;
    // console.log(f instanceof Array); */


    /* // function Fn() { }
    // Fn[Symbol.hasInstance](f)=function (){}//手动加一个 普通构造函数,它的Symbol.hasInstance属性无法被直接修改的,但是ES6语法中可以!!

    class Fn{//新语法重写可以修改
        static[Symbol.hasInstance](){
            console.log('OK');
            if(Array.isArray(obj)) return true;
            return false;
        }
    }
    let f = new Fn;
    let arr=[10,20,30]
    console.log(f instanceof Fn);//=>true
    console.log(arr instanceof Fn);//=>true
    // console.log(Fn[Symbol.hasInstance](f));//=>true   */


    /* // 自己重写 instanceof方法  我们这个方法支持原始值类型
    const instance_of = function instance_of(obj, Ctor) {
        if (Ctor === null) throw new TypeError('Right-hand side of intanceof is not an object');
        let type = typeof Ctor;
        if (!/^object|function)$/i.test(type)) throw new TypeError('Right-hand side of intanceof is not an object');
        if (!/^function)$/i.test(type)) throw new TypeError('Right-hand side of intanceof is not an object');
        if (!Ctor.prototype) throw new TypeError('Function has non-object prototype in instanceof check');
        let proto = Object.getPrototypeOf(obj);
        while (proto) {
            if (proto === Ctor.prototype) return true;
            proto = Object.getPrototypeOf(proto);
        }
        return false;
    };
    console.log(instance_of([], Array));//=>true
    console.log(instance_of([], RegExp));//=>false
    console.log(instance_of(1, Number));//=>true  浏览器默认进行装箱操作 直接检测原型
    console.log(instance_of(Symbol(), Symbol));//=>true 
    console.log(instance_of([], {}));//=>false  但是 instanceof 原本检查会报错 因为右侧不是一个函数(并且必须是函数是个对象有原型[箭头函数会报错(没有原型)])  */


</script>
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享