JS 的类型判断
typeof
结论:null
、function
不符合直觉;无法识别 NaN
、Infinity
和Array
;浏览器实现的对象因浏览器而异
语法:
1 | typeof variable |
对基本数据类型:
typeof null === 'object'
,JavaScript 诞生以来便如此- 其他基本数据类型,返回其对应字符串
注意NaN
和 Infinity
的返回值,尽管语意上和数字有所区别typeof NaN === 'number'
typeof Infinity === 'number'
对引用类型:
typeof someFunction === 'function'
- 其他对象,返回
'object'
注意数组也是 'object'
浏览器实现的非原生对象(host objects)
浏览器环境下的对象,typeof 的实现可能有差异
例如一些 IE 下 typeof alert === 'object'
,尽管它是个 function
toLowerCase()
在搜索判断类型的代码时,经常看到对 typeof
的返回值做 toLowerCase()
,我简单查了一些资料,大部分浏览器对原生的数据类型都会符合预期地返回小写字母,也许这样做是为了处理上文说到的浏览器实现的对象,它们的 typeof
实现千奇百怪,加一个 toLowerCase()
至少不会出错
instanceof
结论
用于判断原型链关系,不能直接判断类型
语法
1 | d instanceof D |
检查 D.prototype
是否在 d
的原型链上
可以粗暴的理解为 d.__proto__.__proto__.__proto__...
这个链中是否有一个节点等于(指向) D.prototype
1 | [].__proto__ === Array.prototype // [] instanceof Array === true |
用途
用于检查引用类型
1 | const a = new A() |
Object 与 Function 的奇妙关系
1 | Object.__proto__ === Function.prototype |
参见另一片文章
Object 与 Function 互为实例的关系,一定程度上也解释了 typeof 上对两者的区分
Object.prototype.toString
toString
会返回一个表示这个对象的字符串,具体格式是
1 | `[object ${type}]` |
个人理解是方括号、第一个 object 都是固定的,根据后边的 type
得到类型
方法的覆盖
很多对象都覆盖了 Object 原有的 toString 方法
1 | (10).toString(2) // '1010',把 number 转换为 string,且是二进制表示 |
因此,需要用 call
或者 apply
的方式,调用 Object
自己的 toString
,具体是 call
还是 apply
无所谓,因为 toString
没有入参
1 | Object.prototype.toString.call([]) // [object Array] |
顺带一提,有这样的写法
Function.prototype.apply.call(fn, this, args)
,而不是直接执行fn.apply(this, args)
,目的就是避免 fn 的 apply 方法已经被重写覆盖过
Object.prototype.constructor
Object.prototype.constructor
指向回创建实例对象的构造函数。
通常来说,它可以判断类型
1 | [].constructor === Array // true |
但这种方式不安全,不可以依赖。
原因在于原型链中可以改写构造函数
1 | const a = new Array() |
实践
判断数组
1 | // 1 |
判断 NaN
isNaN
不够准确,它会把入参尝试转为 Number 之后再判断
1 | isNaN(undefined) // true |
万能函数
1 | const type = (input: any) => { |