常用的判断类型的方式如下
== 有一个类型转换的过程
1 | 1 == '1'; // true,进行类型转换后,字符串 '1' 被转换为数字 1,然后比较相等性 |
就是隐式转换,所以可能会有意想不到的结果。
转换以后对比两个值是否相等,这个是最不推荐的,首先特殊情况很多,还会进行类型转换再来对比,而且只能处理基础类型.
它比 == 好一点的是,他不会进行类型转换,也就是类型相同且值相同的情况下,返回 true.
但是他的缺点依然,就是只能处理基础类型,但是他也有用出。
上面 === 有一个问题
1 | +0 === -0 //true |
然而在 Object.is 中相反
1 | Object.is(+0, -0); //false |
其他结果一致。
typeof 能做的很明确,迅速确定基础类型,比如这里我就是需要 string or number,直接用就好了。
缺点就是可以区分的类型太少了,
typeof 运算符通过检查变量的内部标签来确定其类型。不同类型的变量在内部被赋予了不同的标签
但是这个标签又不对外暴露。
他不能判断复杂类型,比如 new String(), Date, Null 等等,他都返回 object, 而且会混淆 function 和 正则。
所以只能用他判断基础类型,甚至连 function 都不行.
还有很多问题,typeof
1 | typeof null === "object"; |
除了判断某些确定的基础类型,不建议使用
他的逻辑本质上是不停的网上寻找匹配的原型或者构造函数
1 | object instanceof constructor |
按照这个思路,基础类型是无法匹配的
1 | 1 instanceof Number //false |
依照这个思路,我们还可以这样写
1 | function Person() {} |
核心就是不停的往上查,写一个递归.
1 | function myInstanceof(obj, type) { |
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
Object.prototype.toString 是 Object 类原型上的一个方法,用于返回一个表示对象类型的字符串。当我们调用 Object.prototype.toString 方法时,它会检查调用者的内部标签,并返回相应的字符串表示对象类型。
这个就很奇怪了,既然 typeof 也是调用内部的标签,为什么 typeof 不行。
1 | const toString = Object.prototype.toString; |
需要提出的是
1 | Object.prototype.toString.call('1') //[object String] |
这个是没有区分的,但是实际上是有区别的。
还有一个问题是
以这种方式使用 toString() 是不可靠的;对象可以通过定义 Symbol.toStringTag 属性来更改 Object.prototype.toString() 的行为,从而导致意想不到的结果
1 | const myDate = new Date(); |
原理上应该和 Object.prototype.toString.call 一样。
还是要 typoef 和 Object.prototype.toString.call 联合使用才能真正很好的解决问题。
instanceof 真的可以退休了。