jQuery源碼閱讀(十)---jQuery靜態方法分析

jQuery工具方法(靜態方法)是通過jQuery.extend方法來掛在的,extend方法的源碼實現在這篇博客中也有整理過。現在簡單回顧下,當jQuery.extend中的參數爲一個對象時,就是擴展插件的方式,也就是說裏面的方法都會擴展到jQuery上。因此,jQuery工具方法就是這樣實現的。

jQuery.extend({
    //裏面可以擴展的方法
    noConflict: function(){
        //釋放jQuery 對 $ 或者 jQuery 的使用權
    },
    ready: function(fn){
        jQuery.bindReady();
        readyList.add(fn);
        return this;
    },
    isFunction: fucntion( obj ){  },
    isArray: function( obj ){  },
    isWindow: function( obj ){  },
    isNumeric: fucntion( obj ){  },
    type: function( obj ){  },
    isPlainObject: function( obj ){  },
    isEmptyObject: function( obj ){  },
    error: function( msg ){  },
    parseXML: function( data ){  },
    parseJSON: function( data ){  },
    noop: function(){ },
    globalEval: function(){  }
    //等等,後面還有很多工具方法
});

前面兩篇博客(noConflict函數解析jQuery ready函數解析)已經把noConflict 和ready函數這兩個方法做了整理,這一次先整理關於類型檢測的工具方法,即isFunction( obj )、isArray( obj )、isNumeric( obj )、type( obj )、isWindow( obj )、isPlainObject( obj )和 isEmptyObject( obj ) 這幾個函數。

isFunction函數

function( obj ){
    return jQuery.type(obj) === 'function';
}

很簡單,直接調jQuery類型檢測type函數 ,判斷type得到的類型是否與’function’相等。

jQuery.isArray函數

isArray: Array.isArray || function( obj ){
    return jQuery.type( obj ) === 'array';
}

一般來講,利用ES5提供的原生方法isArray是比較快的, 但在某些瀏覽器不支持ES5這種方法時,就調jQuery工具方法type來判斷。

在這裏想到,之前電面時遇到的一道面試題:
如何判斷一個對象是數組類型?有幾種方法?
這裏也簡單總結下:

1. Array.isArray(obj);        //返回true Or false
2. obj instanceof Array       //返回true Or false
3. Object.prototype.toString.call(obj)   //返回類型,如果是數組,返回是'[object Array]'

以上三種方法也有適用性。比如原生的isArray方法,如果瀏覽器不支持ES5,那麼這種方法是不起作用的;instanceof 的話,如果有多個全局環境,比如iFrame,那麼instanceof會受環境的影響。詳見高程第22章高級技巧。

jQuery.isNumeric方法

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

在JS中,typeof NaN也是返回number;所以如果用jQuery.type()方法來判斷的話,是不會過濾掉NaN。另一方面,計算機中數值是有最大最小值的,Number.MAX_VALUE和Number.MIN_VALUE就可以知道最大最小值,所以當數值超過最大最小值時,也就沒有意義了。因此要利用原生方法isFinite()檢查數值是否超過邊界。

isWindow方法

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

window一方面可以是全局對象,一方面又可以是窗口。所以window.window是存在的,並且等於Window對象。
這裏寫圖片描述

因此,只有當obj = window時,obj == obj.window才返回true。

isPlainObject方法

這個函數是判斷一個對象是否爲對象字面值。
這一篇博客中,有說過對象的創建方式,有new方法,有工廠模式,也有對象字面值等等,而isPlainObject方法是判斷對象爲對象字面值或者利用Object()構造函數new出來的對象。

function( obj ){
    //對於空對象,類型爲Array,String,Function,Date...等不是'object'類型的對象,還有DOM對象,Window對象的情況,都認爲不是PlainObject
    if(!obj || jQuery.type( obj ) !== 'object' || obj.nodeType || jQuery.isWindow( obj ))
    {
        return false;
    }

    //對於利用構造函數new出來的對象,但構造函數不是Object,也認爲不是PlainObject
    try {
            // 對於自定義構造函數,然後利用自定義構造函數生成的對象,jQuery.type()返回的是"object"
            // 所以纔有下面的判斷,判斷構造函數,判斷constructor不是自身的屬性,並且'isPrototypeOf'不是構造函數的原型自身的屬性,返回false
            if ( obj.constructor &&
                !hasOwn.call(obj, "constructor") &&
                !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
                return false;
            }
        } catch ( e ) {
            // IE8,9 Will throw exceptions on certain host objects #9897
            return false;
        }

    //個人覺得,下面這部分直接用
    //return true
    //來代替就可以了
    var key;
    for ( key in obj ) {}
    //此時key 等於obj中最後一個屬性名/方法名
    return key === undefined || hasOwn.call( obj, key );
} 

其中

hasOwn = Object.prototype.hasOwnProperty;

這也是jQuery的一大技巧,就是把很多使用比較頻繁的,並且很長的語句用很短的有含義的語句來代替,從而縮小了代碼量,一定程度上也能提高性能。

而在jQuery2.0版本中,前面兩種情況都處理過並未返回false之後,直接返回true.

isEmptyObject方法

空對象裏面是沒有屬性和方法的,所以用for … in來遍歷空對象時,是不會進到循環裏面的。

function( obj ){
    var key;
    for(key in obj)
    {
        return false;
    }
    return true;
}

關於類型檢測的一些靜態方法基本上整理完了,希望大家可以一起探討學習!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章