jQuery源码学习-Type类型检测

type

    • 前置知识
    • 方法实现功能
    • jQuery源码
    • 那还要[Object Number]这样的对象map做什么?
    • 思路
    • 防止覆盖和兼容处理

前置知识


1.Object.prototype.toString()
jQuery源码学习-Type类型检测_第1张图片

这里回忆一下常用的typeof运算符
jQuery源码学习-Type类型检测_第2张图片
jQuery源码学习-Type类型检测_第3张图片
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));

打印结果jQuery源码学习-Type类型检测_第4张图片

方法实现功能

首先要明确$.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源码学习-Type类型检测_第5张图片
准确区分每种数据类型,并以小写返回。

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
主要观察左边
jQuery源码学习-Type类型检测_第6张图片
跟我们之前使用Object.prototype.toString()打印的结果一一对应。


2.把nullundefined单独讨论是因为
后面的代码如果在低版本浏览器中传入nullundefined会打印[object Object]

class2type[ toString.call( obj ) ]

IE5~8

jQuery源码学习-Type类型检测_第7张图片
IE9
jQuery源码学习-Type类型检测_第8张图片

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'
jQuery源码学习-Type类型检测_第9张图片
这个值在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做什么?

jQuery源码学习-Type类型检测_第10张图片
主要是为了判断通过new创建的基本数据类型的实例

思路

  • 创建一个空对象,获取空对象的toString,避免其他对象的toString被覆盖
  • 利用Object.prototype.toString()生成对象map,准确对应了各种引用类型的具体,主要是为了返回它的小写形式
  • 对于nullundefined单独讨论,兼容低版本浏览器
  • 接下来对引用数据类型基本数据类型分开讨论,引用数据类型调用对象原生的toString,准确判断不同类型的引用类型如:Array,Date等,这是typeof无法做到的。
  • 对与基本数据类型,typeof都能准确返回。

防止覆盖和兼容处理

  • 创建普通对象保存原生toString
  • 兼容低版本浏览器对于nullundefined使用{}.toString返回object
  • 兼容低版本对于RegExp返回function
  • 兼容其他不存在的对象,无法精确定位都返回'object

参考文章
https://blog.csdn.net/libin_1/article/details/52649476
原文写的很详细,但是有一些问题,比如$.type的缺陷有待讨论

你可能感兴趣的:(JS)