美文网首页
JS判断数据类型

JS判断数据类型

作者: 元气满满321 | 来源:发表于2017-08-15 11:34 被阅读65次

    在JS中,数据类型包括

    • 基础类型(String、Number、Boolean、Undefined、Null )
    • 引用类型(除 Object 外,还包括 Function 、Array、RegExp、Date 等)

    1. typeof

    简记为
    a.对于基本类型,除null外,其他返回值都有效
    b.对于引用类型,除function返回值有效为function,其他都返回object
    c.null返回值为"object"

    2. instanceof

    instanceof检测对象在其原型链上是否能找到构造函数的prototype属性

    我们用一段伪代码来表示一下instanceof

    instanceof(object,constructor){
      if(object._proto_===constructor.prototype){
        return true
      }else{
        return false;
      }
    }
    

    来举些例子

    
    {} instanceof Object;//true
    new Date() instanceof Date;//true
     
    function Person(){};
    new Person() instanceof Person;
    
    [] instanceof Array; //true
    [] instanceof Object; //true
    
    

    我们发现,虽然 instanceof 能够判断出 [ ] 是Array的实例,但它认为 [ ] 也是Object的实例,为什么呢?

    我们来分析一下 [ ]、Array、Object 三者之间的关系:

    从 instanceof 能够判断出 [ ].proto 指向 Array.prototype,而 Array.prototype.proto 又指向了Object.prototype,最终 Object.prototype.proto 指向了null,标志着原型链的结束。因此,[]、Array、Object 就在内部形成了一条原型链


    从原型链可以看出,[] 的 proto 直接指向Array.prototype,间接指向 Object.prototype,所以按照 instanceof 的判断规则,[] 就是Object的实例

    3. constructor

    当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用。如下所示:



    当执行 var f = new F() 时,F 被当成了构造函数,f 是F的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor == F



    可以看出,F 利用原型对象上的 constructor 引用了自身,当 F 作为构造函数来创建对象时,原型上的 constructor 就被遗传到了新创建的对象上, 从原型链角度讲,构造函数 F 就是新对象的类型

    细节问题

    • null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。
    • 函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object

    为什么变成了 Object?
    因为 prototype 被重新赋值的是一个 { }, { } 是 new Object() 的字面量,因此 new Object() 会将 Object 原型上的 constructor 传递给 { },也就是 Object 本身。
    因此,为了规范开发,在重写对象原型时一般都需要重新给 constructor 赋值,以保证对象实例的类型不被篡改。

    4. toString

    toString 是 Object 原型对象上的方法,使用 call 来调用该方法会返回调用者的类型字符串,格式为 [object,xxx],xxx 是调用者的数据类型,包括:String、Number、Boolean、Undefined、Null、Function、Date、Array、RegExp、Error、HTMLDocument等, 基本上,所有的数据类型都可以通过这个方法获取到。

    Object.prototype.toString.call('') ;   // [object String]
    Object.prototype.toString.call(1) ;    // [object Number]
    Object.prototype.toString.call(true) ; // [object Boolean]
    Object.prototype.toString.call(Symbol()); //[object Symbol]
    Object.prototype.toString.call(undefined) ; // [object Undefined]
    Object.prototype.toString.call(null) ; // [object Null]
    Object.prototype.toString.call(new Function()) ; // [object Function]
    Object.prototype.toString.call(new Date()) ; // [object Date]
    Object.prototype.toString.call([]) ; // [object Array]
    Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
    Object.prototype.toString.call(new Error()) ; // [object Error]
    Object.prototype.toString.call(document) ; // [object HTMLDocument]
    Object.prototype.toString.call(window) ; //[object global] window是全局对象 global 的引用
    

    为什么所有引用类型都会继承toString方法

    因为引用类型继承Object,这个继承也是通过原型链实现的。那就说明引用类型的原型包含一个内部指针指向Object.prototype

    为什么要通过 call 或 apply 来调用

    按照JS原型搜索机制,其他对象应该也可以直接访问到 Object 的 toString方法,而事实上,大部分的对象都实现了自身的 toString 方法,这样就可能会导致 Object 的 toString 被终止查找,因此要用 call/apply 来强制调用Object 的 toString

    每天都努力一点点
    谢谢你看完


    相关文章

      网友评论

          本文标题:JS判断数据类型

          本文链接:https://www.haomeiwen.com/subject/llmmrxtx.html