jQuery源代码学习_工具函数_type
jquery源代码学习_工具函数_type
jquery里面有一个很重要的工具函数,$.type函数用来判断类型,今天写这篇文章,是来回顾type函数的设计思想,深入理解。
首先来看一下最终结果:
上面的源代码乍一看似乎艰涩难懂,有点抽象,毕竟是前辈心血之作,深深佩服。对我们初学者,可以从简单入手,来一步一步深化,得到最终的优化方案。
第一个版本
在看《JavaScript高级程序设计》这本书时候,书上提到typeof,typeof可以判断function,number ,undefined, string, boolean但是用typeof 判断null会返回object,而用typeof判断object返回object,且对于任意的系统对象,比如Regexp,Date,Array等,并不能很好区分。
也就是说:不是object类型的可以使用typeof判断;而对于其他引用类型,我们使用Object.protype.toString。所以可以得到第一个版本的代码如下:
function type(obj) {
if (typeof obj !== 'object') {
return typeof obj;
}
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
对于一些系统对象,用到slice(8,-1),省略了前缀"[object "。不然我们会得到这样结果:
问题
这个函数不能处理type(document.createElement('div'))这样的情况。示例如下:
显然:实际上应该是object类型,而htmldivelement并不是JavaScript数据类型,而是一个DOM的数据类型。
第二个版本
吸取第一个版本的教训,也就是说类型的判断不是盲目的,判断的结果应该在我们所掌握的JavaScript几种数据类型里,那么是哪几种类型呢?除了基本的值类型5种,引用类型Object,还包括Function Array Date RegExp Error一共有11种,因此进一步优化的结果应该是:我们判断的类型取自于以上11种类型里面的任意一个。经常分析处理,我们得到第二个版本的代码如下:
var class2type = 'Boolean Number String Null Undefined Function Array Date RegExp Object Error';
function type(obj) {
if (typeof obj !== 'object') {
return typeof obj;
}
var sliced = Object.prototype.toString.call(obj).slice(8, -1);
return class2type.indexOf(sliced) >= 0 ? sliced.toLowerCase() : 'object';
}
显然我们第一个版本的问题已经解决了。indexOf()方法可返回某个指定的字符串值在字符串中首次出现的位置。
问题
计算量大,每判断一次都要用一个slice、一个indexOf、一个toLowerCase
第三个版本
很明显我们规避使用indexOf方法,把所有的类型结果用对象字面量的方式表现出来,其中key是Object.prototype.toString的计算结果,value是type结果,因此我们可以得到第三个版本的代码如下:
var class2type = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regexp',
'[object Object]': 'object',
'[object Error]': 'error'
};
function type(obj) {
if (typeof obj !== 'object') {
return typeof obj;
}
return class2type[Object.prototype.toString.call(obj)] || 'object';
}
这里用class2type来缓存类型判断的结果。
缺点
这个对象里面全部是字符串,没有办法进行压缩。
第四个版本
借鉴第3种方法的缺陷,我们不用字面量的形式,采用split方法,用空格分隔开类型。
var class2type = {};
var arr = 'Boolean Number String Function Array Null Undefined Date RegExp Object Error'.split(' ');
for (var i = 0, l = arr.length; i < l; i++) {
class2type['[object ' + arr[i] + ']'] = arr[i].toLowerCase();
}
function type(obj) {
if (typeof obj !== 'object') {
return typeof obj;
}
return class2type[Object.prototype.toString.call(obj)] || 'object';
}
这样就不需要枚举所有的类型了,如果需要做额外的判断,只要在字符串中加一个单词就可以了。
第五个版本
继续优化,减少代码量,更高效的方法是用到正则表达式,来匹配每一种类型,它们之间用空格隔开。(据说是司徒正美大神倡导的方法,果然厉害,哇)
var class2type = {};
// 利用replace减少使用for循环,同时可以简化代码
'Boolean Number String Function Undefined Null Array Date RegExp Object Error'.replace(/\w+/g, function (name) {
class2type['[object ' + name + ']'] = name.toLowerCase();
});
function type(obj) {
if (typeof obj !== 'object') {
return typeof obj;
}
return class2type[class2type.toString.call(obj)] || 'object';
}
这样,层层递进,就得到我们伟大的jQuery type源代码啦,是不是很开心呢!
jQuery源代码学习_工具函数_type的更多相关文章
- jQuery源代码学习笔记_工具函数_noop/error/now/trim
jQuery源代码学习笔记_工具函数_noop/error/now/trim jquery提供了一系列的工具函数,用于支持其运行,今天主要分析noop/error/now/trim这4个函数: 1.n ...
- jQuery源代码学习之九—jQuery事件模块
jQuery事件系统并没有将事件坚挺函数直接绑定在DOM元素上,而是基于事件缓存模块来管理监听函数的. 二.jQuery事件模块的代码结构 //定义了一些正则 // // //jQuery事件对象 j ...
- jQuery源代码学习之八——jQuery属性操作模块
一.jQuery属性模块整体介绍 jQuery的属性操作模块分四个部分:html属性操作,dom属性操作,类样式操作,和值操作. html属性操作(setAttribute/getAttribute) ...
- jQuery源代码学习之七—队列模块queue
一.jQuery种的队列模块 jQuery的队列模块主要是为动画模块EFFECTS提供支持,(不过到现在为了支持动画队列的inprogress的出入队还是搞不太清楚),单独抽取出一个命名空间是为了使程 ...
- jQuery源代码学习之六——jQuery数据缓存Data
一.jQuery数据缓存基本原理 jQuery数据缓存就两个全局Data对象,data_user以及data_priv; 这两个对象分别用于缓存用户自定义数据和内部数据: 以data_user为例,所 ...
- jQuery源代码学习之五——jQuery.when
jQuery.when提供了基于一个或多个对象的状态来执行回调函数的功能,通常是基于具有异步事件的异步队列. 如果传入多个异步队列,jQuery.when会返回一个新的主异步队列的只读副本(promi ...
- jQuery源代码学习之四——jQuery.callbacks
自己实现的callbacks模块相较于jquery源代码中的callbacks模块有所简化,表面上看没有考虑firing这个参数,没有对之进行任何处理,即没有考虑在函数执行过程中,再次调用add,re ...
- jquery源码分析-工具函数
jQuery的版本一路狂飙啊,现在都到了2.0.X版本了.有空的时候,看看jquery的源码,学习一下别人的编程思路还是不错的. 下面这里是一些jquery的工具函数代码,大家可以看看,实现思路还是很 ...
- jQuery源代码学习笔记:构造jQuery对象
2.1源代码结构: (function( window, undefined ) { var jQuery = (function() { // 构建jQuery对象 var jQuery = fun ...
随机推荐
- i++,++i,i+=1,i = i+1在C++中的区别
其实这个问题可以从三个角度去分析:语言规范,编译器实现,CPU支持.首先从语言规范上来讲:前置++和后置++是不等价的,前置++在规范中明确指出 和+=组合操作符是等价的,但和E = E+1;这样的赋 ...
- Spring.Net 未将对象引用设置到对象的实例
“/”应用程序中的服务器错误. 未将对象引用设置到对象的实例. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详 ...
- .net core 2.0 jwt身份认证系统
经历了很久,.net core 2.0 终于发布了! 之前一直用的core 1.1,升级了2.0后发现认证的机制(Auth)发生了比较大的变化,在1.1中认证配置是在Configure中完成,而在2. ...
- ubuntu - 14.10,安装uget和aria2(下载工具)
Windows下的下载工具--迅雷,之所以下载速度快,乃是它能搜索资源.为己所用,而不是仅仅从原始地址这单一资源处下载. Ubuntu下也有类似的工具,那就是aira2. aira2是一个命令行下载工 ...
- Linux 下的 etc
/etc etc不是什么缩写,是and so on的意思 来源于 法语的 et cetera 翻译成中文就是 等等 的意思. 至于为什么在/etc下面存放配置文件, 按照原始的UNIX的说法(linu ...
- 洛谷 P2447 [SDOI2010]外星千足虫
P2447 [SDOI2010]外星千足虫 题目描述 公元2089年6月4日,在经历了17年零3个月的漫长旅行后,“格纳格鲁一号”载人火箭返回舱终于安全着陆.此枚火箭由美国国家航空航天局(NASA)研 ...
- socketserver,threading
一,socketserver #server import socketserver class Myserver(socketserver.BaseRequestHandler): def han ...
- dedecms有缩略图则显示缩略图,没有则显示随机缩略图
随着html5以及扁平化等新的设计概念的深入人心,缩略图功能则成了一般网页模版制作不可或缺的一个功能,dedecms默认的的缩略图调用标签[field:imglink/] 或者 [field:litp ...
- Jmeter-逻辑控制器之Switch控制器(Switch Controller)
Switch控制器(Switch Controller): 作用:Switch控制器通过给该控制器中的Value赋值,来指定运行哪个采样器.有两种赋值方式: 第一种是数值,Switch控制器下的子节点 ...
- P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队
\(\color{#0066ff}{ 题目描述 }\) 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支 ...