zoukankan      html  css  js  c++  java
  • 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方法只会对自己添加属性进行遍历,而不会对自带属性遍历。

  • 相关阅读:
    关闭编辑easyui datagrid table
    sql 保留两位小数+四舍五入
    easyui DataGrid 工具类之 util js
    easyui DataGrid 工具类之 后台生成列
    easyui DataGrid 工具类之 WorkbookUtil class
    easyui DataGrid 工具类之 TableUtil class
    easyui DataGrid 工具类之 Utils class
    easyui DataGrid 工具类之 列属性class
    oracle 卸载
    “云时代架构”经典文章阅读感想七
  • 原文地址:https://www.cnblogs.com/y8932809/p/5870970.html
Copyright © 2011-2022 走看看