阅读 91

JavaScript如果正确的判断变量类型

前言

javascript是一门弱类型语言,并且制订初期比较粗糙,类型之间也存在很多隐式转换,很多时候我们不需要进行类型判断也能正确地实现我们的逻辑,但准确的判断类型在很多时候可以减少我们的代码错误,然后在类型判断中也存在很多坑。

这次把常用的变量(关键字)等进行实验,看看怎么判断类型检测最好:

 // 测试的类型: // string  number  boolean  object array  null  undefined // regexp date function class window HTMLDomcument Set Symbol const typeList = [     'string',     1,     true,     {},     [],     null,     undefined,     new RegExp('\s'),     new Date(),     function() {},     class Preson {},     window,     document.getElementById('app'),     new Set(),     Symbol() ] 复制代码

方法一:typeof 函数(关键字)

typeof是javascript提供的最简单的类型判断方法(也是最没用的),可以判断最简单的基础类型,对于对象类型无能为力。

typeof文档

类型检测结果为:

 typeList = [     'string', // string     1, // number     true, // boolean     {}, // object     [], // object     null, // object     undefined, // undefined     new RegExp('\s'), // object     new Date(), // object     function() {}, // function     class Preson {}, // function     window, // object     document.getElementById('app'), // object     new Set(), // object     Symbol() //symbol ] typeList.forEach(el => {     console.log(el,typeof el) }) 复制代码

显然,typeof中很多类型都只能推断为object,只能用于一些基本类型的判断。

方法二:constructor

constructor是对象的构造函数,本着万事皆对象的原则,理论上一切变量都继承自对象类型(Object),而Object的原型链上有constructor属性,这个属性表示了创建该变量的构造函数的引用。

Object.prototype.constructor文档

类型检测结果为:

 console.log('string'.constructor === String) // true let num = 1 console.log(num.constructor === Number) // true console.log(true.constructor === Boolean) // true console.log({}.constructor === Object) // true console.log([].constructor === Array) // true console.log(null.constructor === null) // 报错:Uncaught TypeError: Cannot read properties of null (reading 'constructor') console.log(undefined.constructor === undefined) // 报错:Uncaught TypeError: Cannot read properties of undefined (reading 'constructor') console.log(new RegExp('\s').constructor === RegExp) // true console.log(new Date().constructor === Date) // true console.log((function() {}).constructor === Function) // true console.log((class Preson {}).constructor === Function) // true class Preson {} console.log(new Preson().constructor === Preson) // true console.log(window.constructor === Window) // true console.log(document.getElementById('app').constructor === HTMLDivElement) // true console.log(new Set().constructor === Set) // true console.log(Symbol().constructor === Symbol) // true 复制代码

因为是属性调用,所以nullundefined是无法使用该方法的,且constructor打印出来并不方便观察,所以一般只能用在判断是否等于某一种变量时使用,比如 [].constructor === Array

需要注意的是,constructor是可以被修改的。

方法三:instanceof

instanceofconstructor有些类似:

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

看定义有点绕,举例子说明会好理解些:[] instanceof Array,Array(构造函数)的prototype是否出现在[]的原型链上?

很显然,[]是个数组,它的原型链上一定能找到Array对象以及Array的prototype

instanceof文档

类型检测结果为:

 console.log('string' instanceof String) // false let num = 1 console.log(num instanceof Number) // false console.log(true instanceof Boolean) // false console.log({} instanceof Object) // true console.log([] instanceof Array) // true console.log(null instanceof null) // 报错 console.log(undefined instanceof undefined) // 报错 console.log(new RegExp('\s') instanceof RegExp) // true console.log(new Date() instanceof Date) // true console.log((function() {}) instanceof Function) // true console.log((class Preson {}) instanceof Function) // true class Preson {} console.log(new Preson() instanceof Preson) // true console.log(window instanceof Window)  // true console.log(document.getElementById('app') instanceof HTMLDivElement)  // true console.log(document.getElementById('app') instanceof HTMLElement) // true console.log(new Set() instanceof Set)  // true console.log(Symbol() instanceof Symbol)  // false 复制代码

非引用类型无法通过instanceof来判断类型,同样nullundefined这两个特殊的类型使用instanceof也会报错。

还有两个比较特别的:

  1. Symbol作为一种特别的类型,打印s.prototypeundefined,所以也无法通过instanceof来判断类型。

  2. dom节点,HTMLDivElementHTMLElement都在原型链上,因为HTMLDivElementHTMLElement实际上也是继承关系,所以在原型链接上都存在,同样道理,万物皆对象,以下判断都为true

 [] instanceof Object // true {} instanceof Object // true 复制代码

所以在判断一个变量是数组还是对象时,一定是判断 instanceof Array ,而不是 instanceof Object

方法四:Object.prototype.toString.call

万物皆对象,在这个例子中体现的淋漓尽致,使用这个方法基本上可以区分所有类型:

类型检测结果为:

 const typeList = [     'string', // [object String]     1, // [object Number]     true, // [object Boolean]     {}, // [object Object]     [], // [object Array]     null, // [object Null]     undefined, // [object Undefined]     new RegExp('\s'), // [object RegExp]     new Date(), // [object Date]     function() {}, // [object Function]     class Preson {}, // [object Function]     window, // [object Window]     document.getElementById('app'), // [object HTMLDivElement]     new Set(), // [object Set]     Symbol() // [object Symbol] ]          typeList.forEach(el => {     console.log(el,Object.prototype.toString.call(el)) }) 复制代码

前面几种方法的问题几乎都不再存在,唯一的缺点就是打印结果有点难看,但是好在很标准,所以我们可以通过简单的函数封装,让类型判断更简单一些。

判断类型的方法封装:

 function type(val) {     const type = Object.prototype.toString.call(val)     return type.slice(type.indexOf(" ") + 1,type.length - 1).toLocaleLowerCase() }


作者:蓝德锦
链接:https://juejin.cn/post/7171233789660626951
来源:https://www.77cxw.com/


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐