js当中的类型判断

第一种:type of

1.判断原始类型

我们来看一段代码

js 复制代码
           console.log(typeof(23))
           console.log(typeof (NaN))
           console.log(typeof (true))
           console.log(typeof ('Hello world'))
           console.log(typeof (null))
           console.log(typeof (undefined))

我们来看一下执行结果

type of 可以判断除了null以外的所有原始类型

2.判断引用类型

js 复制代码
          let obj ={}
          let arr=[]
          let date= new Date()
          let fn =function(){

          }
           console.log(typeof (obj))
           console.log(typeof (arr))
           console.log(typeof (date))
           console.log(typeof (fn))

来看一下执行结果

type of 除了function 之外,所有引用类型都会判断成object

问题来了,为什么会这样呢?

原理:事实上,计算机在用type of 判断数据类型时,首先会把数据转化为二进制

原始类型转化二进制前三位一定不是0

引用类型转化为二进制前三位一定是0

type of 总共三句话

1.type of 可以判断除null之外所有的原始类型

2.type of 除了function 其他所有的引用类型都会被判成object

3.type of是通过将值转化为二进制后判断二进制前三位是否为0,是则为object

第二种:instance of

我们来看一段代码

js 复制代码
       
      let num =123
        let string ='hello'  
        let boolen =true 
        let arr=[]
        let obj={}


          console.log(num instanceof Number)
          console.log(string instanceof Number)
          console.log(boolen instanceof Number)

          console.log(arr instanceof Object)
          console.log(obj instanceof Object)

执行结果

说明 instance of 只能判断引用类型数据类型,不能判断基本数据类型

同样的,我们得搞清楚其中的原理

有小伙伴可能会疑惑,为什么 arr instanceof Object 也是true呢?arr是怎么关联到Object的呢?

事实上,这涉及到原型

js 复制代码
      arr.__proto__= Array.prototype
     Array.prototype.__proto__=Object.prototype

这就解决了上面那个问题,为什么instance of 不能判断原始类型呢?

因为原始数据类型没有原型,只有引用数据类型有原型

所以instance of 只能判断引用类型

如果没有instance of ,面试官让你手写以一个类似的 instance of 方法,你该怎么办呢?

js 复制代码
function  myInstanceof (L,R){
       while(L!== null){

         if(L.__proto__===R.prototype){
          return true
         }
         L=L.__proto__
       }
       return false
    }
  

myInstanceof([],Array)
  • 函数接收两个参数:LR。在这里,L 表示要检查的对象(左操作数),而 R 表示构造函数(右操作数)。
  • while 循环中,条件是 L !== null。这是因为当对象的原型链走到尽头时,它会指向 null。只要 L 不是 null,循环就会继续。
  • 在循环体内,使用 if 语句来检查 L 对象的原型(L.__proto__)是否等于 R 构造函数的原型(R.prototype)。如果相等,这意味着 L 实例化自 R 或其原型链上的某个构造函数,所以函数返回 true
  • 如果在当前层级没有找到匹配,将 L 设置为其自身的原型(L.__proto__),然后循环继续到下一层级。
  • 如果循环结束都没有找到匹配,说明 L 的原型链上没有任何构造函数的原型与 R.prototype 相等,因此函数返回 false

第三种:Object.prototype.toString.call()

万能方法:可以判断所有类型

原理:

具体原理

在toString方法被调用时,会执行以下几个操作步骤~

  1. 获取this指向的那个对象的[[Class]]属性的值。 (这也是我们为什么要用call改变this指向的原因)
  2. 计算出三个字符串"[object "、 第一步的操作结果Result(1)、 以及 "]" 连接后的新字符串。
  3. 返回第二步的操作结果Result(2),也就是类似 [object className] 这种格式字符串。

[[Class]] 类属性

对象的类属性(class attribute)是一个字符串,用以表示对象的类型信息。ES3和ES5都没有提供设置这个属性的方法,并只有一种间接的方法可以查询到它。默认的toString方法(继承自Object.prototype)返回了如下格式的字符串:[object class] 因此,想要获得对象的类,可以调用对象的toString方法,然后提取已返回字符串的第8个到倒数第2个位置之间的字符。

javascript 复制代码
js
Object.prototype.toString.call(target).slice(8, -1);

综上,[[Class]]是一个字符串值,表明了该对象的类型。他是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性,且不能被任何人修改。在规范中,[[Class]]是这么定义的:内部属性 描述

宿主对象也包含有意义的"类属性",但这和具体的JavaScript实现有关。

因为js中每个类型都有自己私有的[[Class]]属性,而且这个class是不能被任何人修改的,所以tostring方法是检测属性类型最准确的方法,比instanceof还准确。

他也可以细分内置构造函数创建的类对象

通过内置构造函数(Array、Date等)创建的对象包含"类属性"(class attribute),他与构造函数的名称相匹配(这里也是我从contructor.name来区分数据类型的启发点)。

但是,他无法区分自定义对象类型

通过对象直接量和Object.create创建的对象的类属性是"object",那些自定义构造函数创建的对象也是一样。类属性都是"Object",因此对于自定义类来说,没办法通过类属性来区分对象的类。

为什么用call

这里用call是为了改变toString函数内部的this指向,其实也可以用apply

之所以必须改变this指向是因为,toString内部是获取this指向那个对象的[[Class]]属性值的,如果不改变this指向为我们的目标变量,this将永远指向调用toStringprototype

另外也是因为,很多对象继承的toString方法重写了,为了能调用正确的toString,才间接的使用call/apply方法。

代码演示:

javascript 复制代码
js
复制代码
Object.prototype.toString = function () {
  console.log(this);
};
const arr1 = [];
Object.prototype.toString(arr1); // 打印(即this指向) Object.prototype
Object.prototype.toString.call(arr1); // 打印(即this指向) arr1

为什么null也能判断?undefined和null这两个原始值不是没有属性值吗?

因为每一个类型都有自己唯一的特定 类属性 (class attribute) 标识,null也有、undefined也有。

该方法判断类型的缺陷

他虽然判断类型完善,但也不是没有缺点,主要有两点:

  1. tostring会进行装箱操作,产生很多临时对象 (所以真正进行类型转换时建议配合typeof来区分是对象类型还是基本类型,见最后代码)

  2. 他无法区分自定义对象类型 ,用来判断这类对象时,返回的都是Object(针对"自定义类型"可以采用instanceof区分)

总结一下

1. typeof

  • 用于判断原始类型(除 null 外),能识别 number, string, boolean, undefinedfunction
  • 对引用类型(除 function 外)返回 object

2. instanceof

  • 用于判断引用类型。
  • 检查对象是否为某构造函数的实例。
  • 通过原型链查找,无法判断原始类型。

3. Object.prototype.toString.call()

  • 万能方法,可判断所有类型,包括 nullundefined
  • 返回格式 [object Type]
  • 缺点:对自定义对象类型返回 Object,存在临时对象开销。

总结:typeof 用于基本类型和函数,instanceof 用于引用类型,Object.prototype.toString.call() 是最全面的方法。

制作不易,感谢支持

相关推荐
Yvonne爱编码30 分钟前
CSS- 1.1 css选择器
前端·css·状态模式·html5·hbuilder
山河故人16341 分钟前
uniapp使用npm下载
前端·npm·uni-app
-曾牛1 小时前
基于微信小程序的在线聊天功能实现:WebSocket通信实战
前端·后端·websocket·网络协议·微信小程序·小程序·notepad++
一口一个橘子1 小时前
[ctfshow web入门] web72
前端·web安全·网络安全
Web极客码2 小时前
如何使用WordPress SEO检查器进行实时内容分析
前端·seo·wordpress
Stella25212 小时前
【Vue】CSS3实现关键帧动画
前端·vue.js·css3
junjun.chen06062 小时前
【在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle‘ on ‘Window‘: parameter 1 is not o
前端·javascript·前端框架
Yvonne爱编码2 小时前
HTML-3.3 表格布局(学校官网简易布局实例)
前端·html·github·html5·hbuilder
jllllyuz3 小时前
matlab实现蚁群算法解决公交车路径规划问题
服务器·前端·数据库
小屁孩大帅-杨一凡3 小时前
一个简单点的js的h5页面实现地铁快跑的小游戏
开发语言·前端·javascript·css·html