一、typeof
1.语法: typeof value
2.返回值: 其返回是一个字符串类型的值,常见的有 "number"、"string"、"boolean"、"undefined"、
"object"、"function"、"symbol"、"bigint"
3.优势:使用起来特别方便,检测基本类型和引用类型都可以检测
4.劣势:1.不能细分对象,比如检测 普通对象/数组对象/正则对象...等结果都是Object。就无法细分是普通
对象还是数组对象
2.检测null类型的结果是Object,因为typeof 检测的机制是根据数据类型的值在计算机中存储编码
特征来决定的,对象类型的值在计算中以000开始存储的,而null类型在计算机中全是以0存储的,
所以被识别成对象了,而实际结果null不是对象,这是typeof的检测bug。
5.应用场景: 一般用于检测普通类型以及检测其是否是对象还是函数
检测其是对象或者函数的代码片段如下:
if (x !== null && /^(object|function)$/.test(typeof x)) {
...
}
二、instanceof
1.语法: value instanceof constructor
2.返回值:返回值是个boolean类型,只要实例的原型链有构造函数与其相等就返回true 否则返回false
3.优势:弥补typeof的不足可以细分对象类型,比如检测是否为数组,
4.劣势:1.检测的实例必须是引用类型
2.基本数据类型的实例是无法基于它检测出来的
1.字面量以及非通过new形式创建的实例都无法被检测
2.通过new 构造函数的可以被检测
3.检测的结果会不准如下代码
var x = 10
console.log(x instanceof Number)
var y = Number(10)
console.log(y instanceof Number)
var z = new Number(10)
console.log(z instanceof Number)
var x = [];
console.log(x instanceof Object);
console.log(x instanceof Array)
5.手写一个instanceof 的检测原理
function _instanceof(value, Ctor) {
let prototype = Object.getPrototypeOf(value)
while (prototype) {
if (prototype === Ctor.prototype) return true
prototype = Object.getPrototypeOf(prototype)
}
return false
}
三、constructor
1.语法:value.constructor === 类
2.原理:使用了类上原型的constructor属性指向类本身
3.优势: 使用起来简单并且可以检测基本数据类型
3.劣势: 类的原型容易被重构造成constructor丢失以及constructor属性容易被修改都会造成结果不准确
四、Object.prototype.toString.call()
1.背景: Object原型上的toString调用会返回传入实例的数据类型,而其他对象的toString方法都是把变量
转成字符串
2.语法:Object.prototype.toString.call()
3.返回值: [Object class] 常见的值有[object Number]/[object String]/[object
Boolean]/[object Null]/[object Object]/[object Array]......
4.优势:可以检测任何数据类型
5.劣势:1.性能不如typeof
2. 自定义类的数据类型检测不准 解决方案如下
function Fn() {}
if (typeof Symbol !== undefined) {
Fn.prototype[Symbol.toStringTag] = 'Fn';
}
let fn = new Fn();
console.log({}.toString.call(fn));
五、基于jQuery源码封装的检测数据类型
(function () {
var class2type = {}
var toString = class2type.toString
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) {
return obj + ''
}
return typeof obj === 'object' || typeof obj === 'function'
? class2type[toString.call(obj)] || 'object'
: typeof obj
}
/* 暴露API「支持浏览器直接导入 & webpack CommonJS模块导入」 */
if (typeof window !== 'undefined') {
window.toType = toType
}
if (typeof module === 'object' && typeof module.exports === 'object') {
module.toType = toType
}
})()