javascript的类型检测
1、typeof
typeof操作符可以检测js的基础数据类型,包括number、string、boolean、undefined。因为null在二进制存储的值与object相同,所以typeof检测null会返回object。此为特例
2、instanceof
instanceof操作符可以检测某个对象是否属于某个构造函数,比如
var a = {}
a instanceof Object
// => true
他的原理是,检测对象的原型链中是否存在该构造函数的原型,所以上面的例子,我们可以更改他的结果
var a = {}
a.__proto__ = Boolean.prototype
a instanceof Boolean
// => true
其他
js中检测类型的方式有很多很多,除了以上两种之外,还可以通过constructor函数,或者Array.isArray, isNaN等等方式去判断类型这里不详细记述了
Object.prototype.toString.call
下面我们来介绍一下,今天要分享的主角,登登登~,诶就是Object.prototype.toString.call!
Object.prototype.toString.call可以说是javascript万能的类型检测方式了
请看栗子:
var obj = {}
Object.prototype.toString.call(obj)
// => '[object Object]'
var arr = []
Object.prototype.toString.call(obj)
// => '[object Array]'
var str = ''
Object.prototype.toString.call(str)
// => '[object String]'
var num = 23
Object.prototype.toString.call(num)
// => '[object Number]'
var bol = true
Object.prototype.toString.call(bol)
// => '[object Boolean]'
var nul = null
Object.prototype.toString.call(nul)
// => '[object Null]'
var udf = undefined
Object.prototype.toString.call(udf)
// => '[object Undefined]'
var date = new Date()
Object.prototype.toString.call(date)
// => '[object Date]'
var fn = () => {}
Object.prototype.toString.call(fn)
// => '[object Function]'
var map = new Map()
Object.prototype.toString.call(map)
// => '[object Map]'
var set = new Set()
Object.prototype.toString.call(set)
// => '[object Set]'
var regexp = new RegExp()
var regexp1 = /123/g
Object.prototype.toString.call(regexp)
Object.prototype.toString.call(regexp1)
// => '[object RegExp]'
Object.prototype.toString.call(window)
// => '[object Window]'
…大概有这么多,基本覆盖了所有能想到的类型
而且,这种检测方式相对来说又比较安全稳定,不容易被修改。除非你去覆盖Object.prototype.toSring方法。更改了Object.prototype.toSring方法还用Object.prototype.toSring去检测类型,这有点开玩笑的意思了。
既然这样,如果我定义了一个class
class Test {
toString(){
return 'test'
}
}
const test = new Test()
Object.prototype.toString.call(test)
// => '[object Object]'
我们可以看到,即使我们重新定义了toString方法,并返回一个值,当使用
Object.prototype.toString.call(test)时,还是返回了’[object Object]',那我们该如何定制返回的类型呢?
es6规范
要想了解这个问题,我们必须要去了解es6的规范,其中规范规定了Object.prototype.toString.call的行为,它实际上是返回了被检测对象的Symbol.toStringTag的属性的值,该属性属于语言内部属性,无法被开发者直接访问,也无法在其属性中,原型链中被观测到。但是我们却可以更改这个属性的值。因此,我们也就可以定制Object.prototype.toSring的返回类型了
举例子
var arr = []
arr[Symbol.toStringTag] = '不知名前端'
Object.prototype.toString.call(arr)
// => '[object 不知名前端]'
class Test {
constructor() {
this[Symbol.toStringTag] = '不知名前端'
}
}
const test = new Test()
Object.prototype.toString.call(test)
// => '[object 不知名前端]'
总结
要说这个知识有什么用,在什么场景可以用,可以说基本上是用不上。但是可以了解我们这些常用的方法,到底是什么原理,为什么会有这样的结果。在日常中遇到问题的时候,更能得心应手的排查问题。甚至优化自己的代码