instance

作者:_Fatman
出处:https://www.cnblogs.com/liujingjiu/p/14393105.html
JavaScript中的数据类型分为两类, undefined,number,boolean,string,symbol,bigint,null组成的基础类型 和 Object、Function、Array等类型组成的引用类型。

instance

文章插图
如何判断数据属于哪种类型是JavaScript中非常重要的一个知识点,其中最常用的两个方法就是分别使用typeof与instanceof这两个关键字来对数据的类型进行判断 。
typeof与instanceof虽然都可以用来对数据所属的类型进行判断,但是它们之间还是存在差异的,而这种差异主要存在于两个方面:
1.作用点的不同;
typeof主要用来判断基础数据类型,instanceof则是用来判断引用数据类型 。
2.底层逻辑的不同;
typeof是根据数据在存储单元中的类型标签来判断数据的类型,instanceof则是根据函数的prototype属性值是否存在于对象的原型链上来判断数据的类型 。
typeof判断数据类型共有8个值,它们分别是‘undefined’、‘number’、‘boolean’、‘string’、‘symbol’、‘bigint’、‘object’和‘function’ 。
使用typeof就可以很好的判断数据类型undefined、number、boolean、string、symbol和bigint 。
不过在判断基础类型null时,使用typeof便不再准确了 。这个问题的产生可以追溯到JavaScript的第一个版本,在这个版本中, 单个值在栈中占用32位的存储单元,而这32位的存储单元又可以划分为类型标签(1-3位)和实际数据,类型标签存储于低位中 ,具体可以分成5种:
1.当第0位、第1位和第2位皆为0时,typeof判断此数据类型为’object’;
2.当第0位为1时,typeof判断此数据类型为’number(整数)’;
3.当第0位与第2位皆为0,而第1位为1时,typeof判断此数据类型为’number(浮点数)’;
4.当第0位与第1位皆为0,而第2位为1时,typeof判断此数据类型为’string’;
5.当第1位与第2位皆为1,而第0位为0时,typeof判断此数据类型为’boolean’;
此外还有两种特殊情况:
undefined:整数?2^30 (整数范围之外的数字)
null:第0位到第31位皆为0
当数据值为null时,正好满足当第0位、第1位和第2位皆为0时,typeof判断类型为’object’的条件,所以typeof null === 'object'的结果为true 。
使用typeof判断function也是存在问题的:
在 IE 6, 7 和 8 上,很多宿主对象是对象而不是函数 。
例如:
【instance】typeof alert === 'object';//true还有老版本Firefox中的
typeof /[0-9]/ === 'function';//true像这种的还有很多,就不一样举例了,多半是浏览器实现差异,现在已经统一标准了 。
我在ie11上运行的结果:
typeof alert === 'function';//true在当前最新版Firefox上运行的结果:
typeof reg === 'object';//truetypeof在判断引用类型还存在一些问题,例如:
typeof {} === 'object';//truetypeof [] === 'object';//truetypeof window === 'object';//truetypeof new Map() === 'object';//true这个时候如果想要知道更详细的信息就需要使用instanceof关键字了 。
alert instanceof Function;//true({}) instanceof Object;//true([]) instanceof Array;//truewindow instanceof Window;//true(new Map()) instanceof Map;//true使用instanceof运算符,我们可以清楚的判断对象的原型链上是否存在函数的prototype属性值 。不过instanceof也并不能完全可信,比如通过Symbol.hasInstance属性可以影响instanceof的判断结果:function Person(){}Object.defineProperty(Person,Symbol.hasInstance,{value : function(){return false;}})let p = new Person();p instanceof Person;//false但是Symbol.hasInstance属性并不会影响到数据的原型链,使用自定义的myInstanceof方法不会受到Symbol.hasInstance属性的影响:/*** obj 变量* fn 构造函数*/function myInstanceof(obj,fn){let _prototype = Object.getPrototypeOf(obj);if(null === _prototype){return false;}let _constructor = _prototype.constructor;if(_constructor === fn){return true;}return myInstanceof(_prototype,fn);}function Person(){}Object.defineProperty(Person,Symbol.hasInstance,{value : function(){return false;}})let p = new Person();p instanceof Person;//falsemyInstanceof(p,Person);//true自定义的myInstanceof方法改进版:/*** obj 变量* fn 构造函数*/function myInstanceof(obj,fn){let _prototype = Object.getPrototypeOf(obj);if(null === _prototype){return false;}let _constructor = _prototype.constructor;if(_constructor[Symbol.hasInstance]){return _constructor[Symbol.hasInstance](obj);}if(_constructor === fn){return true;}return myInstanceof(_prototype,fn);}function Person(){}Object.defineProperty(Person,Symbol.hasInstance,{value : function(){return false;}})let p = new Person();p instanceof Person;//falsemyInstanceof(p,Person);//false

秒懂生活扩展阅读