typeof
typeof 对于原始类型来说,除了 null 都可以显示正确的类型
1 | console.log(typeof 2); // number |
typeof 对于对象来说,除了函数都会显示 object,所以说 typeof 并不能准确判断变量到底是什么类型,所以想判断一个对象的正确类型,这时候可以考虑使用 instanceof
instanceof
instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype
1 | console.log(2 instanceof Number); // false |
instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型;
而 typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了 function 类型以外,其他的也无法判断
1 | // 我们也可以试着实现一下 instanceof |
constructor
1 | console.log((2).constructor === Number); // true |
如果创建一个对象,更改它的原型,constructor就会变得不可靠了
1 | function Fn(){}; |
Object.prototype.toString.call()
toString() 是 Object 的原型方法,调用该方法,可以统一返回格式为 “[object Xxx]” 的字符串,其中 Xxx 就是对象的类型。对于 Object 对象,直接调用 toString() 就能返回 [object Object];而对于其他对象,则需要通过 call 来调用,才能返回正确的类型信息。我们来看一下代码。
1 | Object.prototype.toString({}) // "[object Object]" |
1 | function typeOf1(obj){ |
总结
- typeof
- 直接在计算机底层基于数据类型的值(二进制)进行检测
- typeof null为object 原因是对象存在在计算机中,都是以000开始的二进制存储,所以检测出来的结果是对象
- typeof 普通对象/数组对象/正则对象/日期对象 都是object
- typeof NaN === ‘number’
- instanceof
- 检测当前实例是否属于这个类的
- 底层机制:只要当前类出现在实例的原型上,结果都是true
- 不能检测基本数据类型
- constructor
- 支持基本类型
- constructor可以随便改,也不准
- Object.prototype.toString.call([val])
- 返回当前实例所属类信息
判断 Target 的类型,单单用 typeof 并无法完全满足,这其实并不是 bug,本质原因是 JS 的万物皆对象的理论。因此要真正完美判断时,我们需要区分对待:
- 基本类型(null): 使用 String(null)
- 基本类型(string / number / boolean / undefined) + function: - 直接使用 typeof即可
- 其余引用类型(Array / Date / RegExp Error): 调用toString后根据[object XXX]进行判断