typeof检测方式
typeof XXX 返回的都是字符串,字符串中包含的对应的数据类型
检测基本类型值(基本类型值)
typeof '字符串' // => "string"
typeof 1 | 0 | -1 | NaN | Infinity // => 'number'
typeof true | false // => 'boolean'
typeof undefined // => 'undefined'
typeof null(特殊的,空对象指针) // => 'object'
typeof Symbol(1) // => 'symbol'
检测引用类型值
function fn(){}
typeof fn // => 'function'
typeof {} // => 'object'
typeof /^$/ // => 'object'
typeof new Date() // => 'object'
typeof [] // => 'object'
typeof Math // => 'object'
typeof的局限性
- typeof null => 'object',null不是对象,它是空对象指针
- typeof []、/^$/、{}、new Date()、Math等所有的对象类型返回的都是字符串'object',所以无法基于typeof确定具体的对象类型,数组,正则,对象,时间对象等.
instanceof
instanceof检测某个实例是否属于这个类.
instanceof的用法
let arr = [];
arr instanceof Array; // true
arr instanceof RegExp; // false
arr instanceof Object; // true
instanceof的机制:
检测机制: 是所有出现在原型链上的类,检测结果都为true
instanceof局限性
改变原型链的时候,结果就不可靠了.
- 由于可以基于__proto__或者prototype改变原型链的动向,所以基于instanceof检测的结果就不看可靠
- 基本类型值连对象都不是,更没有__proto__属性,虽然说也是所属类的实例,在js中可以调取原型上的方法,但是instanceof是不认的(1 instanceof number)
- 这样instanceof是认的 (new Number(1) instanceof number)
- (12).__ proto__ => (new Number(12)).proto。
let arr = [1,2];
arr.__proto__ = null;
arr instanceof Array; // false
constructor
constructor判断某个实例是不是当前类的实例
constructor用法
let arr = [1,2,3];
arr.constructor == Array // true
constructor的检测机制:
判断某个实例是不是当前类的实例
- arr的原型链指向了Array.prototype,Array.prototype天生自带一个constructor属性,指向Array本身.
constructor局限性
如果当前实例原型改变或者当前实例原型上的constructor改变,就不准确了
当前实例原型改变
let arr = [];
arr.__proto__ = null;
arr.constructor === Array // false
arr.constructor // => undefined
当前实例原型上的constructor改变
let arr = [];
arr.__proto__.constructor = null;
arr.constructor === Array // false
console.log(arr.__proto__.constructor) // null
Object.prototype.toString.call/ ({}).toString.call
Object.prototype.toString,Object原型上的toString方法不是用来转换字符串的,而是用来返回当前类的所属信息的.
Number/String/Boolean/Symbol原型上的toString,valueof方法
- toString 返回的是转换的字符串
- valueof 返回的是原始值
Function/Array/RegExp/Date等原型上的toString方法
- toString 返回的是转换后的字符串
Object原型上的toString方法
- toString: 返回当前实例所属类的信息
- valueOf: 返回原始值,基本类型值
检测依据和返回的格式
检测依据
Object原型上的方法返回的是当前实例所属类的信息
返回的格式=>十种结果
Object.prototype.toString.call({a:1}) // '[object Object]'
Object.prototype.toString.call([]) // '[object Array]'
Object.prototype.toString.call(12) // '[object Number]'
Object.prototype.toString.call('2') // '[object String]'
Object.prototype.toString.call(true) // '[object Boolean]'
Object.prototype.toString.call(fn(){}) // '[object Function]'
Object.prototype.toString.call(/^$/) // '[object RegExp]'
Object.prototype.toString.call(Date()) // '[object Date]'
Object.prototype.toString.call(new Error)// '[object Error]'
Object.prototype.toString.call(Symbol(1))// '[object Symbol]'
局限性
这种方法基本上没有局限性.可快速完成数据类型的检查
JQ源码中如何写的数据类型的检查
var class2Type = {};
'Object Array Number String Boolean Function RegExp Date Error Symbol'.split(' ').forEach(function(item,index){
class2Type.["[object "+item+""]"] = item.toLowerCase();
})
function toType(obj){
if(obj == null){
return ''+obj
}
return typeof obj === 'object' || typeof obj === 'function' ? class2Type(Object.prototype.toString.call(obj)) || 'object' : typeof obj;
}