jQuery源代码学习_工具函数_type

jquery源代码学习_工具函数_type

jquery里面有一个很重要的工具函数,$.type函数用来判断类型,今天写这篇文章,是来回顾type函数的设计思想,深入理解。

首先来看一下最终结果:
261451085204967.jpg
上面的源代码乍一看似乎艰涩难懂,有点抽象,毕竟是前辈心血之作,深深佩服。对我们初学者,可以从简单入手,来一步一步深化,得到最终的优化方案。

第一个版本

在看《JavaScript高级程序设计》这本书时候,书上提到typeof,typeof可以判断function,number ,undefined, string, boolean但是用typeof 判断null会返回object,而用typeof判断object返回object,且对于任意的系统对象,比如Regexp,Date,Array等,并不能很好区分。

261525055524224.jpg
261525166617618.jpg
261525294426557.jpg
261525384741649.jpg
261525470527369.jpg
261525563957191.jpg
261526047244668.jpg
261526165208906.jpg

也就是说:不是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 "。不然我们会得到这样结果:
261535011147239.jpg

问题
这个函数不能处理type(document.createElement('div'))这样的情况。示例如下:
261536233951144.jpg
显然:实际上应该是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';
}

261544095205647.jpg

显然我们第一个版本的问题已经解决了。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源代码啦,是不是很开心呢!


261601275997918.jpg

转载于:https://www.cnblogs.com/QingFlye/p/4368938.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值