本文已参与「新人创作礼」活动,一起开启掘金创作之路
数据类型检测的四种方式
typeof
不能细分对象类型的值,都是返回“object”,函数检测返回“function”。 typeof 10:number typeof new Number(10):object typeof true:boolean typeof new Boolean(true):object typeof “aaa”:string typeof new String("aaa"):object typeof null:object ......
- 底层原理: typeof是按照“值”在计算机中存储的二进制值来检测的,凡是以000开始的都认为是对象(null:00000)。 优点:检测原始值类型和函数类型方便。
instanceof
原本是检测某个对象是否是某个类的实例,临时拉来做数据类型检测,弥补typeof的一些不足,可以细分部分对象。 let arr = []; arr instanceof Array
- 底层原理 arr instanceof Array,首先查找arr[Symbol.hasInstance]是否存在,如果存在基于这个检测Array[Symbol.hasInstance](arr)。如果没有则基于原型链__proto__查找,只要Array.protoType出现在arr的原型链上,返回结果就是true。 arr[Symbol.hasInstance] Array[Symbol.hasInstance](arr) arr.proto == Array.prototype 缺点: 1.不能检测原始值类型; 2.原型链可以重构,导致结果不准确;
constructor
和instanceof类似,都是临时用做数据类型检测使用的,constructor原型可以重构,导致结构不准确。 相对于instanceof,constructor可以检测原始值类型,但是只会基于原型链上的直属类检测。 let arr = []; arr.constructor == Array ------------- true arr.constructor == Object -------------- false ps:因为arr.constructor直接指向的是Array
Object.prototype.toString.call();
除了null/undefined,大部分数据类型所属类的原型上,都有toString方法;但是所有的toString方法都是转换为字符串的只有Object原型上的toString方法是检测数据类型的。 优点:结果准确 返回值:“[object ?]” let obj = {}; obj.toString.call(1)------------------- "[object Number]" obj.toString.call("1")------------------- "[object String]" obj.toString.call(true)------------------- "[object Boolean]" obj.toString.call(new Date(2020-12-12))-- "[object Date]" obj.toString.call(function(){})------------------- "[object Function]" obj.toString.call(null)------------------- "[object Null]" obj.toString.call(undefined)-----------------"[object Undefined]" obj.toString.call([])-----------------"[object Array]"
- 底层原理: 先找要检测值[Symbol.toStringTag],先找私有的,如果找不到再找所属类原型上的,返回的属性值就是“?”; 如果找不到Symbol.toStringTag,则返回当前示例所属构造函数的名字; let f =1; f[Symbol.toStringTag]-------undefined f.constructor[Symbol.toStringTag]-------undefined f.constructor.name -------"Number"