前置知识
🍪
1.Object.prototype.toString()
这里回忆一下常用的typeof
运算符
typeof
检测引用数据类型,只能区分function
,其他引用数据类型,还有Null
都返回的是'object'
因此Object.prototype.toString()
这个方法更加完善
console.log({}.toString.call(1));
console.log({}.toString.call("1"));
console.log({}.toString.call(/1/));
console.log({}.toString.call({}));
console.log({}.toString.call(function() {}));
console.log({}.toString.call([]));
console.log({}.toString.call(true));
console.log({}.toString.call(new Date()));
console.log({}.toString.call(new Error()));
console.log({}.toString.call(null));
console.log({}.toString.call(undefined));
打印结果
方法实现功能
首先要明确$.type()
的作用
console.log($.type(1));
console.log($.type("1"));
console.log($.type(/1/));
console.log($.type({}));
console.log($.type(function() {}));
console.log($.type([]));
console.log($.type(true));
console.log($.type(new Date()));
console.log($.type(new Error()));
console.log($.type(null));
console.log($.type(undefined));
准确区分每种数据类型,并以小写返回。
jQuery源码
//声明普通对象
var class2type = {};
// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
// 因为很多对象上的toString都被改写,因此保存一份
var toString = class2type.toString;
function toType( obj ) {
// 对于null undefined 进行判断 null == undefined : true
if ( obj == null ) {
return obj + "";
}
// Support: Android <=2.3 only (functionish RegExp)
return typeof obj === "object" || typeof obj === "function" ?
class2type[ toString.call( obj ) ] || "object" :
typeof obj;
}
1.这里each遍历数组每一项
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
打印一下class2type
主要观察左边
跟我们之前使用Object.prototype.toString()
打印的结果一一对应。
2.把null
和undefined
单独讨论是因为
后面的代码如果在低版本浏览器中传入null
和undefined
会打印[object Object]
。
class2type[ toString.call( obj ) ]
IE5~8
IE9
3.低版本浏览器中对正则使用typeof检测 返回'function'
, 而不是为了检测函数类型,因为typeof function(){} 返回的就是正常的'function'
return typeof obj === "object" || typeof obj === "function" ?
class2type[ toString.call( obj ) ] || "object" :
typeof obj;
}
接下来引用数据类型调用toString.call( obj )
基本上都能判断 || "object"
避免没检测到的情况,比如说新版本的Set
类
检测到的为'object'
这个值在class2type对象里就没有,了解了源码以后其实我们可以添加上去。
jQuery.each("Set Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
console.log($.type(new Set)); //=>'set'
当然了 并不建议这么做。
检测到基本数据类型就直接返回,typeof
对于基本数据类型是准确的。
那既然这样,可能会有一个疑问
⭐️⭐️⭐️⭐️
那还要[Object Number]这样的对象map做什么?
主要是为了判断通过new
创建的基本数据类型的实例
思路
- 创建一个空对象,获取空对象的
toString
,避免其他对象的toString被覆盖 - 利用
Object.prototype.toString()
生成对象map,准确对应了各种引用类型的具体,主要是为了返回它的小写形式 - 对于
null
和undefined
单独讨论,兼容低版本浏览器 - 接下来对
引用数据类型
和基本数据类型
分开讨论,引用数据类型
调用对象原生的toString
,准确判断不同类型的引用类型如:Array
,Date
等,这是typeof
无法做到的。 - 对与
基本数据类型
,typeof
都能准确返回。
防止覆盖和兼容处理
- 创建普通对象保存原生
toString
- 兼容低版本浏览器对于
null
和undefined
使用{}.toString
返回object
- 兼容低版本对于
RegExp
返回function
- 兼容其他不存在的对象,无法精确定位都返回
'object
参考文章
https://blog.csdn.net/libin_1/article/details/52649476
原文写的很详细,但是有一些问题,比如$.type的缺陷有待讨论