
检测数据类型的四种办法
发布日期:2021-05-04 20:18:21
浏览次数:30
分类:技术文章
本文共 6152 字,大约阅读时间需要 20 分钟。
JS中数据类型检测的办法
1. typeof [value]
- 语法 :
typeof [value]
:返回一个字符串,字符串中包含了对应的数据类型 - 优势:检测基本类型值(原始值类型,不含null)以及函数等值的检测还是很准确的,操作方便
- 原理:根据计算机底层存储值的 “ 二进制值 ” 来检测的「性能会好一些」
- 劣势:
typeof null => "object"
typeof
检测数组,对象、正则等都是object
,不能细分对象typeof typeof [] -> "string"
2. [实例] instanceof [构造函数]
- 本意: 检测当前实例是否属于这个类;用来检测数据类型,仅是“临时拉来当壮丁”,所以存在很多弊端「可以基于instanceof细分对象类型」
- 语法:
[实例] instanceof [构造函数]
- 原理:首先按照
[构造函数][Symbol.hasInstance]([实例])
- 如果存在这个属性方法,则方法执行返回的值就是最后检测的结果
- 如果不存在这个属性方法,则会查找当前[实例]的原型链,一直找到
Object.prototype
为止 - 如果查找中途,找到的某个原型等于"构造函数"的原型「即构造函数的原型出现在其原型链上」则返回结果是true,反之false
- 优势:对于数组、正则、对象可以细分一下
- 劣势:基本数据类型无法基于它来检测
- 检测原理:
- 构造函数
[Symbol.hasInstance](实例)
- 检测当前构造函数的原型
prototype
是否出现在,当前实例所处的原型链上__proto__
,如果能出现结果就是true - 在JS中原型链是可以改动的,所有结果不准确
- 所有实例的原型链最后都指向
Object.prototype
,所以实例 instacnceof Object
的结果都是true - 字面量方式创造的基本数据类型值是无法基于
instanceof
检测的「浏览器默认并不会把它转换为new的方式」,所以它本身不是对象,不存在__proto__
这个东西
- 构造函数
3. [对象].constructor===[构造函数]
- 和instanceof类似,也是非专业检测数据类型的,但是可以这样处理一下
- 语法:[val].constructor === 类
- 优势:相对于instanceof来讲基本数据类型也可以处理,而且因为获取实例的constructor,实际上获取的是直接所属的类,所以在检测准确性上比instanceof还好一点
- 劣势:constructor可以被随意修改
4. Object.prototype.toString.call([value])
- 在其他数据类型的内置类原型上有toString,但是都是用来转换为字符串的 ,只有Object基类原型上的toString是用来检测数据类型的。
- 所属构造函数的信息是根据 Symbol.toStringTag 获取的「有这个属性基于这个获取,没有浏览器自己计算」
- obj.toString() obj这个实例调用Object.prototype.toString执行,方法执行里面的THIS是当前操作的实例OBJ,此方法就是检测实例THIS的数据类型的,返回的结果:"[object 所属类]" =>[万物皆对象,所属的类]
- Object原型上的toString并不是用来转换为字符串的,而是用来检测数据类型的,
- 检测的方法:执行Object.prototype.toString方法,因为this是谁,就检测谁的数据类型,所以通过call强制改变this是[val],就相当于在检测val的数据类型 <=> ({}).toString.call([val])
- 这种方法是最强大的检测方案,准确率最高,就是代码稍稍冗余
- let obj={name:‘zhufeng’}; obj.toString -> Object.prototype.toString let arr=[]; arr.toString -> Array.prototype.toString 鸭子类型「原型上方法的借用」 =>Object.prototype.toString.call(arr) =>({}).toString.call(arr)
JS中创建一个值有两种方案:
- 字面量方式 let n = 100; let obj1 = {};
- 构造函数方式 「不能 new Symbol/new BigInt -> Object(symbol/bigint) 其他基本类型值也可以这样处理,但是都要排除null/undefined」 let m = new Number(100); let obj2 = new Object();
对于基本数据类型,两种方式的结果是不一样的:
- 字面量方式得到的是基本数据类型「特殊的实例」,而构造函数方式得到的是对象类型「正规的实例」
- 对于引用数据类型,两种方式除了语法上的一些区别,没有本质的区别,获取的都是对应类的实例对象
其他快捷办法
- Array.isArray([value]) :检测value是否是数组
- isNaN([value]):检测[value]是否为有效数字
JQ部分源码分析
(function () { var class2type = { }; var toString = class2type.toString; //Object.prototype.toString 检测数据类型的 var hasOwn = class2type.hasOwnProperty; //Object.prototype.hasOwnProperty 检测是否私有属性的 var fnToString = hasOwn.toString; //Function.prototype.toString 把函数转换为字符串 var ObjectFunctionString = fnToString.call(Object); //=>"function Object() { [native code] }" var getProto = Object.getPrototypeOf; //获取当前对象的原型链__proto__ // 建立数据类型检测的映射表 { "[object Array]":"array",....} var mapType = ["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error", "Symbol", "BigInt"]; mapType.forEach(function (name) { class2type["[object " + name + "]"] = name.toLocaleLowerCase(); }); // 检测数据类型的办法 var toType = function toType(obj) { if (obj == null) { // 传递的是 null/undefined return obj + ""; } // 基于字面量方式创造的基本数据类型,直接基于typeof检测即可「性能要高一些」; // 剩余的基于Object.prototype.toString.call的方式来检测,把获取的值到映射表中匹配,匹配结果是字符串对应的数据类型; return typeof obj === "object" || typeof obj === "function" ? class2type[toString.call(obj)] || "object" : typeof obj; }; // 检测是否为函数 var isFunction = function isFunction(obj) { // typeof obj.nodeType !== "number" :防止在部分浏览器中,检测
发表评论
最新留言
第一次来,支持一个
[***.219.124.196]2025年04月05日 03时49分13秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
删除外键约束
2019-03-01
c++ 预处理命令 #error 用法
2019-03-01
Qt Creator编码
2019-03-01
Linux部署sendmail邮件服务器
2019-03-01
【今日CV 计算机视觉论文速览 第97期】Tue, 9 Apr 2019
2019-03-01
庄子:谁知南华秋水意?
2019-03-01
Thread.sleep() 和 Thread.yield() 区别
2019-03-01
第1讲 快速入门 《Kotlin 极简教程 》
2019-03-01
官宣:湘江智能“车-站-路-云”一体化协同智慧公交解决方案来啦!
2019-03-01
UltraEdit不产生bak 文件可能不是DOS格式
2019-03-01
云计算-大数据-云安全高等教育改革示范教材
2019-03-01
Web站点安全监控
2019-03-01
使用MaxCompute进行数据质量核查
2019-03-01
JavaScript 自学手册(文档教程)
2019-03-01
Java语言特点与学习
2019-03-01
阿里云数据库MySQL版快速上手!
2019-03-01
数据库表设计-------三个范式
2019-03-01
夜光带你走进Vue.js(三十二)擅长的领域
2019-03-01
夜光精讲 Opentcs 三大算法(十三)调度算法
2019-03-01