JS53 判断变量类型
总结了几种判断JavaScript中变量类型的方法。
学到了
instanceof
在iframe
中的问题,去美团面试又被拒了吧。(2018.12.13)知其然不知其所以然,只知道可以用
intanceof
和constructor
,区别又不知道,去头条面试又被拒了吧(2018.12.3)
总结
最常用的判断方法是Object.prototype.slice.call()
,其他判断的方法都有着各种问题:
Array.isArray
判断数组,需要ES6的支持typeof
有各种特殊情况instanceof
对于字面量不适用,并且在iframe场景中有问题constructor
是可以手动改写的
Object.prototype.toString
也有着风险:Object.prototype.toString
的结果可以使用Symbol.toStringTag
定义(2019.02.01)
方法1 typeof
不太靠谱的方法,对于基本类型是可以的
1 | typeof 123 |
对于引用类型行不通,判断结果都是object
1 | typeof [] |
方法2:instanceof
instanceof
运算符用来验证原型对象与实例对象之间的关系。
==当a.___proto___ === A.prototype
成立时,instanceof
返回true
==
1 | var a = [], |
但是注意:
1 instanceof
只对引用类型有效,==对于基本类型字面量是无效的==,因为基本类型不是对象,不存在原型链的继承关系
1 | [] instanceof Array; |
2 instanceof
存在继承关系,==对于引用类型都是Object
的实例==
1 | [] instanceof Array; |
3 instanceof
在iframe的场景中有可能出现误判
1 | const a = [1, 2, 3]; |
可以认为宿主和iframe是两套JS的执行环境,环境中的Array是不同的,所以判断会出现问题。
方法3:constructor
实质上实例是没有constructor
属性的,其constructor
属性是继承自原型的:
1 | function Person(){}; |
应用时:
1 | var a = [], |
它的主要问题是:constructor
是可以手动更改的,当通过原型继承时,constructor
会被改写
1 | function Person() {}; |
instacnceof
和constructor
的区别
instanceof
是操作符,而constructor
是继承构造函数的原型的一个属性instanceof
对于基本类型的字面量是无效的(返回false
),基本类型的字面量的constructro
不存在instancoeof
存在继承性,引用类型都是Object
的实例,而constructor
是可以认为改写的
1 | undefined instanceof Object; |
方法4 Array.isArray()
ES6的Array.isArray()
方法可以来判断数组的类型
1 | var a = [], |
方法5 toString
方法
首先要知道,调用Object.prototype.toString
返回结果都是[object xxx]
的格式,例如:
1 | Object.prototype.toString.call({}) |
构造一个函数,isType
,传入要验证的类型,返回值是一个新的函数:
1 | function isType(type) { |
这是一个比较稳妥的判断方法。
Object.prototype.toString
也有着风险:Object.prototype.toString
的结果可以使用Symbol.toStringTag
定义:
1 | var o = { [Symbol.toStringTag]: "MyObject" }; |
参考
- JavaScript高级程序设计(第3版)
- 掘金 - 高阶函数,你怎么那么漂亮呢!