🎯总结
-
typeof
操作符 -
instanceof
操作符 -
Object.prototype.toString.call()
方法
typeof 操作符
- 用于类型判断,返回一个字符串。
- 字符串 ➡️
'string'
- 数值 ➡️
'number'
- 布尔值 ➡️
'boolean'
- undefined ➡️
'undefined'
- null ➡️
'object'
- Symbol 值 ➡️
'symbol'
- 一般函数、箭头函数、Generator 函数、async 函数、class ➡️
'function'
- 其它对象 ➡️
'object'
- 字符串 ➡️
-
总结
- 可以精确识别基本数据类型值(除 null 以外)
- 可以从引用数据类型值中识别出函数
- 无法精确识别除函数之外的引用数据类型值,而是会被识别为
'object'
。
instanceof 操作符
-
用于检测某个对象是否为给定构造函数的实例,若是则返回 true,否则 false。
- 基本数据类型值 instanceof 任意构造函数 ➡️
false
- 原始引用数据类型的实例 instanceof 原始引用数据类型/Object ➡️
true
- 自定义引用数据类型的实例 instanceof 自定义引用类型/自定义引用类型的各祖先类/Object ➡️
true
- 基本数据类型值 instanceof 任意构造函数 ➡️
-
针对上述最后一点,始终返回 true 的前提是在定义好各构造函数、类之后,不再修改相应构造函数、类的整个 prototype。下面给出一个反例:
function Animal() {} function Cat() {} Cat.prototype = new Animal() let cat1 = new Cat() console.log(cat1 instanceof Cat) // true console.log(cat1 instanceof Animal) // true console.log(cat1 instanceof Object) // true // 修改了 Cat 构造函数的整个 prototype Cat.prototype = {} console.log(cat1 instanceof Cat) // false console.log(cat1 instanceof Animal) // true console.log(cat1 instanceof Object) // true let cat2 = new Cat() console.log(cat2 instanceof Cat) // true console.log(cat2 instanceof Animal) // false console.log(cat2 instanceof Object) // true
-
总结
- 无法识别基本数据类型值
- 可以精确识别原始引用数据类型值
- 可以识别自定义引用数据类型值,但无法定位到最精确的构造函数、类上面去。
实际原理:判断某个对象的原型链上是否存在给定构造函数的原型对象 prototype,若存在则返回 true。
-
下面模拟实现了 instanceof 操作符
function isInstanceOf(instance, constructor) { const list = ['string', 'number', 'boolean', 'undefined', 'symbol'] const type = typeof instance const isBasicVal = instance === null || list.indexOf(type) > -1 const prototype = constructor.prototype let proto = isBasicVal ? null : instance.__proto__ while (proto) { if (proto === prototype) { return true } proto = proto.__proto__ } return false }
Object.prototype.toString.call() 方法
-
用于类型判断,返回一个表示数据类型的字符串。
- 字符串、String 实例 ➡️
'[object String]'
- 数值、Number 实例 ➡️
'[object Number]'
- 布尔值、Boolean 实例 ➡️
'[object Boolean]'
- undefined ➡️
'[object Undefined]'
- null ➡️
'[object Null]'
- Symbol 值 ➡️
'[object Symbol]'
- 一般函数、箭头函数、class ➡️
'[object Function]'
- Generator 函数 ➡️
'[object GeneratorFunction]'
- async 函数 ➡️
'[object AsyncFunction]'
- Date 实例 ➡️
'[object Date]'
- 正则表达式 ➡️
'[object RegExp]'
- 数组 ➡️
'[object Array]'
- Object 实例、自定义引用数据类型的实例 ➡️
'[object Object]'
- 字符串、String 实例 ➡️
-
针对上述最后一点进行举例:
// Object 实例 console.log(Object.prototype.toString.call({}) === '[object Object]') // true // 自定义引用数据类型的实例 function Animal() {} console.log(Object.prototype.toString.call(new Animal()) === '[object Object]') // true class Cat() {} console.log(Object.prototype.toString.call(new Cat()) === '[object Object]') // true
-
总结
- 可以识别基本数据类型值,但字符串、数值、布尔值这三个与它们各自相对应的包装类型是无法进行区分的。
- 可以精确识别原始引用数据类型值,注意对 Generator 函数和 async 函数的类型区分。
- 无法识别自定义引用数据类型值,而是会被识别为
'[object Object]'
。