在我们开始了解有关js的类型判断之前,我们先来了解一下js两类数据类型分别是哪些:
基本类型:string、number、undefined、null、boolean、symbol、bigint。
引用类型:Array、Object、Function、Date、Set、Map。
一、typeof
-
typeof 可以正确判断除了 null 以外的所有数据类型
-
typeof 判断引用类型,除了 function 以外,都返回 object
ini
let s = 'hello'
let n = 123
let f = true
let u = undefined
let nu = null
let sy = Symbol(1)
let b = 1234523423n
let arr = []
let obj = {}t
let fun = function () { }
let date = new Date()
let set = new Set()
let map = new Map()
当我们分别用函数console.log(typeof())
执行打印时就会发现:

为什么打印基本类型 null 会出现 object 呢?
原因:typeof 是通过将值转化为二进制来判断类型的,对于二进制前三位是 0 的统一识别为对象,而所有引用类型转换成二进制前三位都是 0,null 的二进制全是 0
为什么打印引用类型 function 会出现 function 而不是 object 呢?
原因:函数得到 typeof === 'function'
是 JavaScript 的刻意设计,目的是明确标识可调用实体,尽管它在技术上是对象的一种子类型。这种区分提高了代码的可读性和类型检查的实用性。
二、instanceof
- 可以准确判断引用类型,判断的机制是通过判断对象的隐式原型链来查找是否存在左边某一项等于右边的 prototype
- 不能判断基本的数据类型(基本数据类型默认不访问隐式原型,所以无法识别那些基本类型)
ini
let s = 'hello'
let n = 123
let f = true
let u = undefined
let nu = null
let sy = Symbol(1)
let b = 1234523423n
let arr = []
let obj = {}t
let fun = function () { }
let date = new Date()
let set = new Set()
let map = new Map()
当我们分别用函数console.log(X instanceof *)
执行打印时就会发现(由于Undefined 和 Null 都没有构造函数,所以我们这边就注释掉这两行):
javascript
console.log(arr instanceof Array);
console.log(arr instanceof Object);
console.log(obj instanceof Object);
console.log(fun instanceof Function);
console.log(date instanceof Date);e
console.log(set instanceof Set);
console.log(map instanceof Map);
console.log(s instanceof String);
console.log(n instanceof Number);
console.log(f instanceof Boolean);
// console.log(u instanceof Undefined);
// console.log(nu instanceof Null);
console.log(sy instanceof Symbol);
console.log(b instanceof BigInt);

看打印结果可知:instanceof 只能判别引用类型,而无法判别基本数据类型(引用类型全为 true ,基类型全为 false )。 而为什么第二行代码也会返回 true 呢? arr.proto === Array.proyotype.proto === Object.prototype.proto 这就类似于儿、父、爷的大小关系。
javascript
function myInstanceof(L, R) {
let L = L.__proto__
while(L){
if (L === R.prototype){
return true
}
L = L.__proto__
}
return false
}
console.log(myInstanceof([], Array));
可以通过这串代码来实现寻找某个函数的显示原型是否存在这个函数的隐式原型。
三、Array.isArray
当执行这行代码时:console.log(Array.isArray({})
会返回 false
当执行这行代码时:console.log(Array.isArray([])
会返回 true
所以这个函数只能用于判断里面是否为一个数组。
注意:isArray 没有添加在 Array 的原型上,所以 isArray 不能数组的实例对象访问。
四、Object .prototype.toString.call()
目前Object .prototype.toString.call()
是用于判断数据类型最准确的方法。
-
如果 this 值未定义,则返回" [object Undefined] "。
-
如果 this 值为null,则返回" [object Null] "。
-
让 O 成为调用 ToObject 并将 this 值作为参数传递的结果。
-
令 class 为 O 的 [[Class]] 内部属性的值。
-
返回连接三个字符串" [object ", " class "和" ] "的字符串值。

这里我们需要用 this 的显性绑定规则(显示绑定 fn.call(obj, x, x, ...)
显示的将 fn 里面的 this 绑定到 obj 上, call 负责帮 fn 接收参数),来将那个 this 指向Object .prototype.toString.call()
中的括号里面的内容去实现识别并返回其中的数据类型。
