2021-07-03 JS中数据类型检测汇总

  • typeof [value]:检测的结果是一个字符串,字符串中包含了对应的数据类型

    • 缺点:
      1. typeof null => “object”
      2. typeof不能细分对象(除函数)
    • 优点:typeof检测速度快,性能好
    • 底层原理:
      • 所有数据类型值,在计算机底层都是按照“64位,2进制”来存储的,所有对象数据类型值,前三位都是“0”,而存储null的二进制代码全是0
      • typeof就是按照二进制值来进行检测的(性能好),例如:它认为前三位是0的就是对象,在这基础上再看对象是否实现了call方法,如果实现了结果就是“function”,没有实现,结果就是“object”,所有它也不能细分对象
  • instanceof:检测某个实例是否属于这个类

    • 作用:弥补typeof的不足,可以把对象类型进行细分

    • 问题:结果不一定准确

    • 原理:基于instanceof检测的时候,value instanceof Ctor

      • 先看Ctor(构造函数)是否存在[Symbol.hasInstance]这个属性方法,如果存在,则基于这个方法进行检测,Ctor[Symbol.hasInstance](value)

      • 如果没有这个属性方法,获取value的原型链(直到找到Object.prototype为止),如果Ctor.prototype出现在它的原型链上,则证明value是Ctor的实例,反之则不是…

      • 在新版本浏览器中,在Function.prototype上存在一个属性方法 Symbol.hasInstance,所以只要是函数「不论是普通函数,还是构造函数」,都具备 Symbol.hasInstance 这个方法…

      • 可以基于构造函数静态方法重写[Symbol.hasInstance]方法

      class Fn {
          static[Symbol.hasInstance](val) {
              return false;
          }
      }
      let f = new Fn;
      console.log(f instanceof Fn); //false
      console.log(Fn[Symbol.hasInstance](f));
      
    • 重写instanceof方法

    const instance_of = function instance_of(obj, ctor) {
    // 格式检验
    if (typeof ctor !== "function") throw new TypeError('Right-hand side of instanceof is not callable');
    if (!ctor.prototype) throw new TypeError('Function has non-object prototype in instanceof check');
    if (obj === null || !/^(object|function)$/i.test(typeof obj)) return false;
    // 支持Symbol.hasInstance的直接使用这个方法
    let hasInstance = typeof Symbol !== "undefined" && ctor[Symbol.hasInstance];
    if (hasInstance) {
        return hasInstance.call(ctor, obj); //ctor[Symbol.hasInstance](obj)
    }
    // 不支持的,我们需要自己按照原型链进行查找
    let proto = Object.getPrototypeOf(obj);
    while (proto) {
        if (proto === ctor.prototype) return true;
        proto = Object.getPrototypeOf(proto);
    }
    return false;
    

};
```

  • constructor:获取实例的构造函数

    • 写法:n.constructor === Array/RegExp/Object…
    • 缺点:答案不准确
    • 优点:可以检测一个对象是否为标准普通对象「纯粹对象」 是Object的直属实例 (实例.proto===Object.prototype)
    • 内部操作:(1).constructor -> 把原始值的1默认变为对象类型的实例 new Number(1) “装箱:把原始值默认转换为其构造函数创造的对象类型实例,这样就可以调用所属类原型上的方法了”
  • object.prototype.toString.call([value])

    • 大部分类的原型上都有toString方法,都是用来转换为字符串的…但是Object.prototype.toString不是用来转换为字符串的,而是检测数据类型的…
    • 这个方法忒好用了…除了写起来麻烦一些,几乎没有漏洞
    • 返回结果 “[object ?]”
    • 写法:Object.prototype.toString.call([value]);
    • Object.prototype.toString.call([value])的底层原理
      • 先检查[value][Symbol.toStringTag]属性,如果有这个属性,属性值是啥 @X,最后检测的结果就是 “[object @X]”
      • 如果没这个属性,则按照自己所属的内置类进行处理…
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值