类型判断
简单数据类判断
typeof
-
typeof可以准确判断除了null以外的基本数据类型 -
typeof判断引用数据类型,除了function以外,其他的都返回object
typeof是通过将值转换成二进制来判断类型的,对于二进制前三位是 0 的统一识别为对象而所有的引用类型二进制前三位都是
0同时,
null的二进制全是0
来点代码看看吧:
let s = 'hello'
let n = 123
let f = true
let u = undefined
let sy = Symbol(1)
let b = 1231231231n
let nu = null
console.log(typeof(s)); // string
console.log(typeof(n)); // number
console.log(typeof(f)); // boolean
console.log(typeof(u)); // undefined
console.log(typeof sy); // symbol
console.log(typeof b); // bigint
console.log(typeof nu); // object --不能对null进行识别
接下来看看复杂数据类型中使用typeof的表现:
let arr = []
let obj = {}
let date = new Date()
let set = new Set()
let map = new Map()
let fun = function() {}
console.log(typeof arr); // object
console.log(typeof obj); // object
console.log(typeof date); // object
console.log(typeof set); // object
console.log(typeof map); // object
console.log(typeof fun); // function
可以看到,
typeof对除了function以外的所有复杂数据类型都束手无策统统输出object
复杂数据类型
instanceof
-
能准确判断引用类型,不能判断基本数据类型
-
需要使用形如:
s instnceof Class -
判断的机制是:通过对象的隐式原型链来查找是否存在某一项等于右边的 prototype
上代码:
let s = 'hello' // string
let n = 123 // number
let f = true // boolean
let u = undefined // undefined
let nu = null // object
let sy = Symbol(1) // symbol
let b = 1231231231n // bigint
let obj = {}
let fun = function() {}
let date = new Date()
let set = new Set()
let map = new Map()
// 复杂数据类型统统拿下
console.log(obj instanceof Object); // true
console.log(fun instanceof Function); // true
console.log(date instanceof Date); // true
console.log(set instanceof Set); // true
console.log(map instanceof Map); // true
// 简单数据类型全军覆没
console.log(s instanceof String) // false
console.log(n instanceof Number) // false
console.log(f instanceof Boolean) // false
console.log(sy instanceof Symbol) // false
console.log(b instanceof BigInt) // true
手写instanceof
function myInstanceof(L, R) {
L = L.__proto__
while(L) {
if (L === R.prototype) {
return true
}
L = L.__proto__
}
return false
}
console.log(myInstanceof([], Array)); // 检验
console.log(myInstanceof([], Object)); // 检验
追问:根据instanceof机制,以下代码的输出内容是什么?
let arr = []
console.log(arr instanceof Array)
console.log(arr instanceof Object)
聪明的同学应该知道,两个代码的结果都是true,根据原型链的关系,Array也是属于Object的。
图解:原型链及原型链详解
既然数组和对象这么难搞
那么接下来我们介绍一个万金油的判断方法
万能大法
Object.prototype.toString.call()
- 如果
this value未定义 ,则返回[object Undefined] - 如果
this value为null,则返回[object Null] - 设
O为调用ToObject的结果,将this值作为参数传递 - 设
class为O的[Class]内部属性的值 - 返回
String值,该值是[object class]
代码示例:
Object.prototype.toString.call(123); // "[object Number]"
Object.prototype.toString.call("hello"); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(function(){}); // "[object Function]"
// 注意的是,Object.prototype.toString.call 方法返回的字符串格式为 "[object 类型]"
// 封装
function typeOf(data) {
return Object.prototype.toString.call(data).slice(8, -1); //修改输出格式
}
// 测试
console.log(typeOf(1)); // Number
console.log(typeOf("1")); // String
console.log(typeOf(true)); // Boolean
console.log(typeOf(null)); // Null
console.log(typeOf(undefined)); // Undefined
console.log(typeOf(Symbol(1))); // Symbol
console.log(typeOf({})); // Object
console.log(typeOf([])); // Array
console.log(typeOf(function () {})); // Function
console.log(typeOf(new Date())); // Date
console.log(typeOf(new RegExp())); // RegExp
isXXX方法
Array.isArray方法可以判断一个对象是否为数组Number.isNaN可以判断一个值是否为NaNNumber.isFinite可以判断一个值是否为有限数
console.log(Array.isArray([1, 2, 3])); // true
console.log(Array.isArray({})); // false
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(123)); // false
console.log(Number.isNaN("hello")); // false
console.log(Number.isFinite(123)); // true
console.log(Number.isFinite("hello")); // false
console.log(Number.isFinite(Infinity)); // false
总结
-
typeof可以准确地判断出基本类型,但是对于引用类型除function之外返回的都是object; -
已知是引用类型的情况可以选用
instanceof进行具体类型的判断:instanceof是基于原型链的 -
Object.prototype.toString.call()通用但很繁琐