LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

三种“类型判断”的方法,一起手写instanceof方法的实现原理

freeflydom
2023年11月27日 11:58 本文热度 476

在Javascript中,有三种常用的方法用于判断数据类型:

1. typeof操作符

typeof操作符是最常用的判断数据类型的方法之一。它是一个一元操作符,可以用于判断一个值的数据类型,并返回一个表示该数据类型的字符串。常见的typeof返回值有:

- "undefined": 用于表示未定义的变量
- "number": 用于表示数字类型
- "string": 用于表示字符串类型
- "boolean": 用于表示布尔类型
- "object": 用于表示对象类型(包括数组、日期、正则表达式等)
- "function": 用于表示函数类型
- "bigint": 用于表示大数字类型
- "symbol": 用于保证创建的值不与其他属性名产生冲突

例如:

typeof undefined; // "undefined"  

typeof 42; // "number"  

typeof "hello"; // "string"  

typeof true; // "boolean"  

typeof { name: "John" }; // "object"  

typeof function() {}; // "function"  

typeof 123n; // "bigint"

typeof symbol('hello'); //"symbol"

需要注意的是,typeof对于null的判断返回的是"object",这是因为在Javascript的早期版本中,null被错误地认为是一个对象。而对于函数类型,则返回"function".

2. instanceof操作符

instanceof操作符用于判断一个对象是否属于某个构造函数的实例。它比typeof更适用于判断对象类型,因为它可以准确地判断多层原型链中的实例关系。例如:

var arr = [];  

var date = new Date();  

var obj = {};

var fn = function(){};

  

arr instanceof Array; // true  

date instanceof Date; // true  

obj instanceof Object; // true  

fn instanceof Function; // true  

instanceof判断的结果是一个布尔值,如果对象是指定构造函数的实例,则返回true,否则返回false。

同时,也正是因为instanceof操作符可以判断多层原型链中的实例关系,那函数和数组不也可以看作是一个对象吗,那用他们用instanceof操作符来判断和Object的关系,是不是也能得到true呢,我们来看一看:

var arr = []; 

var fn = function(){};


arr instanceof Object; // true  

fn instanceof Object; // true  

结果也是true,欸,arr instanceof Array是true,arr instanceof Object也是true,这时候我们是不是开始好奇instanceof方法的实现原理了,怎么这两个结果都能是true呢。

这时候我们不妨先来大胆猜测一波,我们都知道,arr数组的创建实际是通过new构造函数Array()得到的,那arr就是构造函数Array()的一个实例对象,所以当我们判断arr instanceof Array时, 如果在instanceof方法实现原理内部,用arr的隐式原型(arr.__proto__)去和Array的显示原型(Array.prototype)比较,相等就返回true,否则返回false,通过原型的知识,这么想arr instanceof Array返回true是不是非常合情合理。(注:如果还有不太懂原型知识的小伙伴可以先看看我之前的原型知识文章喔~
但是,又好像还差一点吼,那用刚刚那个想法判断arr instanceof Object,这时候就要用arr的隐式原型(arr.__proto__)去和Object的显示原型(Object.prototype)进行比较了,那他两是不是很明显就不相等了,这时估计有看过我原型文章聪明的小伙伴知道了,这时候他们不相等,arr的隐式原型arr.__proto__对象会再用它的隐式原型,也就是arr.__proto__.__proto__,再去和Object的显示原型(Object.prototype)进行比较,这时候会发现他们是不是就相等啦,结果返回true。
欸,对喽!就是这样思路!非常的棒!实例对象 instanceof 数据类型 就是先通过判断实例对象.__proto和数据类型的prototype是否相等,相等直接返回true,不相等就通过原型链,再往上找,看实例对象.__proto.__proto和数据类型的prototype是否相等,要是还不相等就再往上,直到实例对象.__proto.__proto.__proto为null了,还是和数据类型的prototype不相等,则返回false。
那我们带着这个思路是不是非常清晰的就知道了instanceof方法的实现原理啦!接下来,我们一起手写代码来实现一下叭!代码如下:

//L 实例对象

//R 要判断的数据类型

function instanceOF(L,R){

    while(L !== null){

        // 用实例对象的__proto__属性和要判断的数据类型的prototype进行判断

        //相等返回true,不相等再用实例对象的__proto__的__proto__属性去判断

        //直到L.__proto__.__proto__...为null,就通过原型链根本找不到相等的了,返回false.

        if(L.__proto__ === R.prototype){  

            return true

        }

        else L = L.__proto__

    }

    return false

}


//验证我们手写的instanceOF是否正确

console.log(instanceOF([],Array)); //true

console.log(instanceOF([],Object));//true

所以,搞明白之后,是不是觉得手写instanceof方法非常简单啦!好,那既然数组,函数用instanceof方法和object数据类型进行判断都为true,所以这种方法好像也不是那么完美,并不能精准判断对象的类型。那我们不妨看看下面另一种方法。

3. Object.prototype.toString方法

Object.prototype.toString是一个通用的方法,可以返回一个对象的内部属性[[Class]]的值,从而判断对象的类型。toString方法被重写,并通过不同的内部属性来标识不同的类型。例如:

Object.prototype.toString.call(undefined); // "[object Undefined]"  

Object.prototype.toString.call(42); // "[object Number]"  

Object.prototype.toString.call("hello"); // "[object String]"  

Object.prototype.toString.call(true); // "[object Boolean]"  

Object.prototype.toString.call({ name: "John" }); // "[object Object]"  

Object.prototype.toString.call(function() {}); // "[object Function]"  

这时小伙伴要问啦,不是讲Object.prototype.toString方法嘛,怎么后面还跟了一个call方法呢,好,这时候我们试试不加call方法,看看结果如何:

console.log(Object.prototype.toString(undefined))// "[object Object]"

console.log(Object.prototype.toString(42))// "[object Object]"  

console.log(Object.prototype.toString("hello"))// "[object Object]" 

这时会发现结果都是[object Object]对象类型,当直接调Object.prototype.toString时,它的 this 值会被设置为 toString 方法的调用者,也就是要检查类型的对象本身,这里就是Object.prototype对象,所以得到的结果都是对象类型。这时可以通过call方法来改变它的调用者,从而将this值设置为我们想要检查类型的对象。这样做可以确保我们获取到了准确的内部属性 [[Class]] 的信息,用于判断对象的类型。所以,使用Object.prototype.toString.call方法可以准确地检查对象的类型,而不受调用者的影响。这是一种常用的方法来判断对象类型的标准做法。


作者:小米露
链接:https://juejin.cn/post/7299742103688265769
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



该文章在 2023/11/27 11:58:52 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved