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的更多相关文章

  1. jQuery源代码学习笔记_工具函数_noop/error/now/trim

    jQuery源代码学习笔记_工具函数_noop/error/now/trim jquery提供了一系列的工具函数,用于支持其运行,今天主要分析noop/error/now/trim这4个函数: 1.n ...

  2. jQuery源代码学习之九—jQuery事件模块

    jQuery事件系统并没有将事件坚挺函数直接绑定在DOM元素上,而是基于事件缓存模块来管理监听函数的. 二.jQuery事件模块的代码结构 //定义了一些正则 // // //jQuery事件对象 j ...

  3. jQuery源代码学习之八——jQuery属性操作模块

    一.jQuery属性模块整体介绍 jQuery的属性操作模块分四个部分:html属性操作,dom属性操作,类样式操作,和值操作. html属性操作(setAttribute/getAttribute) ...

  4. jQuery源代码学习之七—队列模块queue

    一.jQuery种的队列模块 jQuery的队列模块主要是为动画模块EFFECTS提供支持,(不过到现在为了支持动画队列的inprogress的出入队还是搞不太清楚),单独抽取出一个命名空间是为了使程 ...

  5. jQuery源代码学习之六——jQuery数据缓存Data

    一.jQuery数据缓存基本原理 jQuery数据缓存就两个全局Data对象,data_user以及data_priv; 这两个对象分别用于缓存用户自定义数据和内部数据: 以data_user为例,所 ...

  6. jQuery源代码学习之五——jQuery.when

    jQuery.when提供了基于一个或多个对象的状态来执行回调函数的功能,通常是基于具有异步事件的异步队列. 如果传入多个异步队列,jQuery.when会返回一个新的主异步队列的只读副本(promi ...

  7. jQuery源代码学习之四——jQuery.callbacks

    自己实现的callbacks模块相较于jquery源代码中的callbacks模块有所简化,表面上看没有考虑firing这个参数,没有对之进行任何处理,即没有考虑在函数执行过程中,再次调用add,re ...

  8. jquery源码分析-工具函数

    jQuery的版本一路狂飙啊,现在都到了2.0.X版本了.有空的时候,看看jquery的源码,学习一下别人的编程思路还是不错的. 下面这里是一些jquery的工具函数代码,大家可以看看,实现思路还是很 ...

  9. jQuery源代码学习笔记:构造jQuery对象

    2.1源代码结构: (function( window, undefined ) { var jQuery = (function() { // 构建jQuery对象 var jQuery = fun ...

随机推荐

  1. tftp命令详解

    TFTP协议简介TFTP是用来下载远程文件的最简单网络协议,它其于UDP协议而实现.嵌入式linux的tftp开发环境包括两个方面: 一是linux服务器端的tftp-server支持,二是嵌入式目标 ...

  2. 解决Mac版微信小程序开发工具打开后无法显示二维码

    问题描述: 正常情况下,打开微信小程序开发工具后,首页提示扫描二维码进行登陆,但是如果不显示二维码,当然无法登陆. 解决方案: 无法显示二维码肯定是程序运行哪里出错了,我们直接点击桌面图标是无法排查错 ...

  3. angular 分页2

    http://www.alliedjeep.com/2547.htm AngularJS Code (Users.js) var Users = angular.module('Users', []) ...

  4. java 集合(转载)

    一.集合与数组 数组(可以存储基本数据类型)是用来存现对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用. 集合(只能存储对象,对象类型可以不一样)的长度可变,可在多数情况下使用. ...

  5. java java web及tomcat的使用

     java web及tomcat的使用 一.什么是java web: 参考百度百科: http://baike.baidu.com/link?url=HnaWXFD7wFfPAlFMW02GV6r5p ...

  6. K-Dominant Character (模拟)

    You are given a string s consisting of lowercase Latin letters. Character c is called k-dominant iff ...

  7. b,u,i,s,这些被删除的标签以及用来替换他们的标签

    加粗文字 给文字加下划线 倾斜文字 给文字加删除线 这些是以前的HTML语言修饰文字用的,没有语义,所以被删除,不到万不得已 不能使用,HTML给了新的标签替换他们,并且有语义 定义重要性强调的文字 ...

  8. echarts设置地图大小比例,大小设置

    设置地图大小可通过以下属性设置: geo.aspectScale number [ default: 0.75 ] 这个参数用于 scale 地图的长宽比. 最终的 aspect 的计算方式是:geo ...

  9. MobaXterm替换cmder

    Windows上命令行工具cmder确实很好用,其扩展功能呢,比系统自带强大几倍.后来在使用MobaXterm,官网https://mobaxterm.mobatek.net/免费版本功能足够强大,支 ...

  10. kuangbin专题十六 KMP&&扩展KMP HDU4300 Clairewd’s message

    Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important ...