• JQuery源码解析-JQuery的工具方法(2)


    这篇对下面的方法进行讲解:

      isFunction():是否为函数

      isArray():是否为数组

      isWindow():是否为window

      isNumeric()是否为数字

      type():判断数据类型

      isPlainObject():是否为对象自变量

      isEmptyObject():是否为空的对象

    isFunction方法:

    这个方法很简单,判断对象是否为函数,返回bool类型,看一下源码:

    // See test/unit/core.js for details concerning isFunction.
        // Since version 1.3, DOM methods and functions like alert
        // aren't supported. They return false on IE (#2968).
        isFunction: function( obj ) {
            return jQuery.type(obj) === "function";
        },

    源码很简单,通过调用jQuery.type方法判断返回值是否为function,这里需要注意的是注释部分,注释上说在IE老的版本浏览器中,从1.3以后就对DOM的方法和原生的方法不在支持了,这时返回的是false。

    isArray方法:

    isArray: Array.isArray,

    可以看到这里直接用原生数组的方法,这也是因为原生的方法速度会比较快,所以有原生方法还是最后用原生的方法。

    isWindow方法:

    isWindow: function( obj ) {
            return obj != null && obj === obj.window;
        },

    这个方法用来判断是否为window对象,这里用到了两个条件,先来看第一个:

    obj != null,和null进行比较,只有null和undefined比较才会为真,所以这里先对这两种情况进行判断,以免后面的条件报错。

    obj === obj.window 如果是window对象的话,其实下面的属性还会有个window属性,并且可以一直无限的调用例如: window.window.window.window.. 

    这里先不说具体原因,等到以后在进行说明。

    isNumeric方法:

    isNumeric: function( obj ) {
            return !isNaN( parseFloat(obj) ) && isFinite( obj );
        },

    这个方法用来判断是否为number类型,那么这里为什么这么麻烦,而不是直接用typeof方法判断呢,是因为:

     console.log(typeof NaN); //number

    可以看到,用typeof方法判断NaN的时候返回也是number,所以为了可靠,不能使用原生的方法。

    第一个条件中,先对参数进行转换,如果可以的话,那也就是为number类型,如果转换不了,返回的是NaN,也就不满足条件了。

    第二个条件用了一个isFinite方法,这个方法是用来判断数字是否在可用范围内,因为计算机计算的数据有限,有时可能传入一个很大的数字,超出了计算机的运算范围,这里也返回false。

    console.log(isFinite(Number.MAX_VALUE+Number.MAX_VALUE)); //false

    type方法:

    type方法返回的是传入参数的数据类型,如:

      function a(){};
      console.log($.type(a)); //function

    源码:

    type: function( obj ) {
            if ( obj == null ) {
                return String( obj );
            }
            // Support: Safari <= 5.1 (functionish RegExp)
            return typeof obj === "object" || typeof obj === "function" ?
                class2type[ core_toString.call(obj) ] || "object" :
                typeof obj;
        },

    首先对传入的参数进行判断,如果为null或undefined,直接返回这两种类型的字符串。

    接下来判断参数是否为object或者function,如果是,则运行class2type[ core_toString.call(obj) ] || "object" ,否则直接返回 typeof obj就可以了,因为这种情况只能是基本类型,用typeof判断就足够了。

    下面详细介绍这里最重要的一句:

    class2type[ core_toString.call(obj) ] || "object"

    core_toString对象其实就是{}.toString方法。在源码56行:

    core_toString = class2type.toString,

    可以找到,下面介绍一下这个tostring方法:

      var arr=new Array();
      console.log({}.toString.call(arr)); //[object Array]

    这个方法还可以对date、function等进行判断,我们可以知道,如果用原生的方法,例如date类型,那返回的是object,如:

    var arr=new Array();
    console.log(typeof arr); //object

    所以最好使用这种情况进行类型的判断,这种判断是相当准确的。

    下面在看一下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();
    });

    可以看到,这个方法把所有类型都放到了这个对象里,然后拼好 [object +name] 对应的属性名和简写的值,那以后直接就可以通过属性名找出对应简写的数据类型了。

    isPlainObject方法:

    这个方法是判断是否为对象自变量的。返回bool值,源码:

    isPlainObject: function( obj ) {
            // Not plain objects:
            // - Any object or value whose internal [[Class]] property is not "[object Object]"
            // - DOM nodes
            // - window
            if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
                return false;
            }
    
            // Support: Firefox <20
            // The try/catch suppresses exceptions thrown when attempting to access
            // the "constructor" property of certain host objects, ie. |window.location|
            // https://bugzilla.mozilla.org/show_bug.cgi?id=814622
            try {
                if ( obj.constructor &&
                        !core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
                    return false;
                }
            } catch ( e ) {
                return false;
            }
    
            // If the function hasn't returned already, we're confident that
            // |obj| is a plain object, created by {} or constructed with new Object
            return true;
        },

    第一个条件:

    if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
                return false;
            }

    这里先进行判断,如果不是obj类型,或者是节点类型,也或者是window对象,那么直接返回false。

    // Support: Firefox <20
            // The try/catch suppresses exceptions thrown when attempting to access
            // the "constructor" property of certain host objects, ie. |window.location|
            // https://bugzilla.mozilla.org/show_bug.cgi?id=814622
            try {
                if ( obj.constructor &&
                        !core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
                    return false;
                }
            } catch ( e ) {
                return false;
            }

    这里对另一种情况进行判断,有一种特殊的情况就是传入window.location的时候,因为上面的判断语句无法对这种情况进行判断。

    首先判断这个对象是否有constructor,如果有,在判断其原型上是否有isPrototypeOf方法,如果没有,那么则返回false,core_hasOwn:

    core_hasOwn = class2type.hasOwnProperty,

    从这里可以看到这里之前调用object的hasOwnProperty方法。

    这段代码为什么要用try呢,注释中的说明是因为在火狐20一下的版本中,如果多次调用window.location.contructor时,可能会出现too much recursion 这个错误,具体原因请看:https://bugzilla.mozilla.org/show_bug.cgi?id=814622

    isEmptyObject方法:

    这个方法用来判断是否为空对象。

    isEmptyObject: function( obj ) {
            var name;
            for ( name in obj ) {
                return false;
            }
            return true;
        },

    这里看如直接用for in 方法来处理,如果对象内有属性,则会被 for in到,返回false。另外for in方法只会对自己添加属性进行遍历,而不会对自带属性遍历。

  • 相关阅读:
    shell 冒泡算法 解决数组排序问题
    react(二)
    react(一)
    mybatis-plus:3
    lambda
    配置中心(nacos)-控制台使用
    nacos作为配置中心的简单项目配置
    nacos作为注册中心的简单项目配置
    Vue初步学习
    nacos单例模式简单搭建
  • 原文地址:https://www.cnblogs.com/y8932809/p/5870970.html
Copyright © 2020-2023  润新知