前言
首先我们要搞懂JS的数据类型有哪些,ES6之前JS的数据类型有6种,在ES6(包括ES6)之后新增了两种数据类型 Symbol(ES6)、Bigint(ES10)。
JS的数据类型:undefined、null、boolean、string、number、object、symbol、bigint
基本数据类型:undefined、null、boolean、string、number、symbol、bigint
引用数据类型:object、function、array、Date、RegExp、Set、Map
判断数据类型方法
- typeof
- instanceof
- Constructor
- Object.prototype.toString.call()
typeof
typeof 能判断出 undefined、boolean、number、string、object、function、symbol、bigint,
它常用于判断基本数据类型。
typeof能判断所有的基本数据类型吗?
不能,他不能判断 null。typeof null 为 object
在开始之前,先声明常见的数据类型
const num = 1 // number
const str = '123' // string
const bol = false // boolean
const fun = function() {} // function
const obj = {} // object
const arr = [] // array
const sym = Symbol() // symbol
const bint = 10n // bigint
const und = void(0) // undefined
const nul = null // null
const dat = new Date() // date
const rep = /12/g // regexp
const set = new Set() // set
const map = new Map() // map
现在我们来测试一下
typeof num // number
typeof str // string
typeof bol // boolean
typeof fun // function
typeof obj // object
typeof arr // object
typeof sym // symbol
typeof bint // bigint
typeof und // undefined
typeof nul // object
typeof dat // object
typeof rep // object
typeof set // object
typeof map // object
instanceof
instanceof用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上
object instanceof constructor
object 某个实例对象
constructor 某个构造函数
我们来看下使用场景
function Cat() {}
function Dog() {}
const c = new Cat()
c instanceof Cat // true, 因为c的隐式原型 == Cat.prototype
c instanceof Dog // false, 因为Dog.prototype不在c的原型链上
c instanceof Object // true 因为Object在c的原型链上
instanceof判断右边的原型是否在左边的原型链上,根据这个思路我们来手写一下myInstanceof
const myInstanceof = (left, right) => {
let lp = left.__proto__
while(lp) {
if(lp === right.prototype) return true
lp = lp.__proto__
}
return false
}
这样我们就能实现基础功能,但是还有两个问题
-
在判断
myInstanceof(1, Number)是true,我们使用a instance Number是false -
在判断
myInstanceof(Cat, Object)是false,使用Cat instanceof Object是true
为了解决这两个问题,代码修改如下
const myInstanceof = (left, right) => {
if(typeof left !== 'object' && typeof left !== 'function') return false
let lp = left.__proto__
while(lp) {
if(lp === right.prototype) return true
lp = lp.__proto__
}
return false
}
这样就解决了上面的两个问题
Construtor
Constuctor能判断出大多数的数据类型,但是不能判断出undefined和null,因为他俩没有constructor
num.constructor.toString()) // function Number(){[native code]}
str.constructor.toString()) // function String(){[native code]}
bol.constructor.toString()) // function Boolean(){[native code]}
fun.constructor.toString()) // function Function(){[native code]}
obj.constructor.toString()) // function Object(){[native code]}
arr.constructor.toString()) // function Array(){[native code]}
sym.constructor.toString()) // function Symbol(){[native code]}
bint.constructor.toString()) // function Bigint(){[native code]}
und.constructor.toString()) // Cannot read properties of undefined (reading 'constructor')
nul.constructor.toString()) // Cannot read properties of null (reading 'constructor')
dat.constructor.toString()) // function Date(){[native code]}
rep.constructor.toString()) // function RegExp(){[native code]}
set.constructor.toString()) // function Set(){[native code]}
map.constructor.toString()) // function Map(){[native code]}
Object.prototype.toString.call()
Object.prototype.toString.call()能判断出所有的类型,全能选手。
Object.prototype.toString.call(num)) // [object Number]
Object.prototype.toString.call(bol)) // [object Boolean]
Object.prototype.toString.call(str)) // [object String]
Object.prototype.toString.call(fun)) // [object Function]
Object.prototype.toString.call(obj)) // [object Object]
Object.prototype.toString.call(arr)) // [object Array]
Object.prototype.toString.call(sym)) // [object Symbol]
Object.prototype.toString.call(bint)) // [object Bigint]
Object.prototype.toString.call(und)) // [object Undefined]
Object.prototype.toString.call(nul)) // [object Null]
Object.prototype.toString.call(dat)) // [object Date]
Object.prototype.toString.call(rep)) // [object Regexp]
Object.prototype.toString.call(set)) // [object Set]
Object.prototype.toString.call(map)) // [object Map]
Object.prototype.toString.call(new WeakMap)) // [object WeakMap]
我们可以用slice方法就可以把类型提取出来了
function getType(el) {
return Object.prototype.toString.call(el).slice(8, -1).toLowerCase()
}
结语
现在对数据类型和数据类型判断大概有了清晰的知识结构,如果有问题,欢迎小伙伴们指正🥳