首頁  >  文章  >  web前端  >  從jQuery應該明白哪些知識?

從jQuery應該明白哪些知識?

零下一度
零下一度原創
2017-06-17 15:41:111160瀏覽

最近想看一下jquery源碼,搜到了這樣一篇博客《從jQuery源碼學到的10件事情》

本文基於這篇視頻博客,提煉了一些內容,分享給大家。

說明:
這篇文章寫於2010年,作者在影片裡使用的是jQuery 1.4版本,我根據影片裡講到的內容,對應目前的1字頭1.11版本做了一些調整,一些被拋棄或被移除的內容頁做了刪減,並在此感謝原作者

#黑箱/Black box

黑箱系統的概念是給定輸入返回輸出的一個系統,黑箱把實現過程進行封裝。這裡說的jQuery黑箱是為js全域變數window輸出jQuery 和 $,而過程被封裝到黑箱裡,與外界互不干擾。

jQuery 1.4版本的黑箱是利用了類似如下的自執行函數

(function( window, undefined){})(window)

作者給了一個比較通用的實現黑箱的方法

undefined = true;
(function(window, document, undefined){    
    if(foo == undefined) {
        }
})(this, document)

jQuery的黑箱裡多傳了第三個形參叫做undefined,而傳實參的時候並沒有傳值,js裡沒有傳值的形參會被設定為undefined,保證了黑箱內部undefined的正確性。在js中,undefined作為一個全域屬性,是可以被賦值的,例如上述程式碼中的undefined = true;

以自執行函數的模式實現黑箱的另一個好處是利於壓縮,例如下述的情況,我們只需要在黑箱內部使用簡單的變數。

(function(A, B, C)){
    B.getElementById('')
})(this, document)

作者為匿名函數自執行舉了很多例子,比如下面這個,為頁面的某一部分不停地更新(以及不斷地執行)

(function loop(){
    doStuff();
    $('#update').load('awesomething.php',function(){
        loop();
    })
    //setTimeout(loop, 100)
})()

jQuery 1.11版本的黑箱採用了全新的工廠方法,本文不探究

noConflict的實作

這個函數的差異不大,1.11 版本程式碼如下

var
    // Map over jQuery in case of overwrite
    _jQuery = window.jQuery,
    // Map over the $ in case of overwrite
    _$ = window.$;
jQuery.noConflict = function( deep ) {
    if ( window.$ === jQuery ) {
        window.$ = _$;
    }
    if ( deep && window.jQuery === jQuery ) {
        window.jQuery = _jQuery;
    }
    return jQuery;
};

我們可以看到防衝突的實作是先把之前的JQuery 和$ 存起來,noConflict被呼叫的時候,再還給它們

與原生js屬性命名的轉換

##1.4版本用的是props物件來存放jquery對

屬性操作與原生js屬性操作的對應關係1.11版縮減版本是這樣的

jQuery.extend({
    propFix: {
        "for": "htmlFor",
        "class": "className"
    },
    prop: function( elem, name, value ) {
        //...
        name = jQuery.propFix[ name ] || name;
    },
    propHooks: {
        //...
    }
});
jQuery.each([
    "tabIndex",
    "readOnly",
    "maxLength",
    "cellSpacing",
    "cellPadding",
    "rowSpan",
    "colSpan",
    "useMap",
    "frameBorder",
    "contentEditable"
], function() {
    jQuery.propFix[ this.toLowerCase() ] = this;
});

propFix 這個物件是存放對應關係表的,例如class轉換成className,prop函數負責處理這個關係表。

而下面的each很有意思,
遍歷數組中那些屬性,然後把他們小寫格式對應到自己,放到 propFix

特效Speed

#我們知道在jQuery裡一些動畫我們可以直接透過normal,fast,slow 來定義實現速度,這個在原始碼裡是這樣定義的

jQuery.fx.speeds = {
    slow: 600,
    fast: 200,
    // Default speed
    _default: 400
};

調皮的原作者做了這樣一些事情:

var isIE 
//...
jQuery.fx.speeds._default = isIE ? 800 : 400
jQuery.fx.speeds.veryfast = 200;
$('...').fadeIn('veryfast')

一種是可以對default屬性做

條件判斷,還有一個自訂速度,例如”veryfast”

.ready

ready函數1.11版本和1.4版本有較大的差距,新版中很多東西我也不太能理解,我們就簡單的把核心拿出來看一下

jQuery.ready.promise = function( obj ) {    //...省略若干        } else if ( document.addEventListener ) {            // 使用addEventListener "DOMContentLoaded" 监听ready事件            document.addEventListener( "DOMContentLoaded", completed, false );            // 备选方案 "load"            window.addEventListener( "load", completed, false );        //如果IE        } else {            // Ensure firing before onload, maybe late but safe also for iframes                        //IE下 attachEvent 的"onreadystatechange"            document.attachEvent( "onreadystatechange", completed );            // A fallback to window.onload, that will always work                        //备选方案onload            window.attachEvent( "onload", completed );            // If IE and not a frame            // continually check to see if the document is ready            var top = false;            try {                top = window.frameElement == null && document.documentElement;            } catch(e) {}            if ( top && top.doScroll ) {                (function doScrollCheck() {                    if ( !jQuery.isReady ) {                        try {                            // Use the trick by Diego Perini                            // http://javascript.nwbox.com/IEContentLoaded/                            top.doScroll("left");                        } catch(e) {                            return setTimeout( doScrollCheck, 50 );                        }                        // detach all dom ready events                        detach();                        // and execute any waiting functions                        jQuery.ready();                    }                })();            }        }    }    return readyList.promise( obj );};
.ready 利用了下面的.promise去做确保载入完成的工作,重点是document.addEventListener( "DOMContentLoaded", completed, false );window.addEventListener( "load", completed, false );document.attachEvent( "onreadystatechange", completed );window.attachEvent( "onload", completed );

相容性考慮的四種檢查方式


#其中從top開始,做了一件事情就是IE下面,dom節點判斷是否有scroll,在IE下如果dom有scroll,沒有scroll到的元素對ready會有影響,這裡面我的理解不夠,總之jQuery裡面用到了一個叫做Diego Perini的技巧,可以在註解裡的地址看到更多內容。

選擇器

$('#id').find('tag.thing') --- faster


$('#id tag.thing') ------- using sizzle

原作者在這裡說了一個jquery效率的問題,上面的方法更快一些,而下面的方法稍微慢,簡單地說是因為下面的方法呼叫了sizzle,透過sizzle其實轉換成上述的模式,而id的呼叫則是直接過jQuery.init.

這裡需要擴充一下,我們來看一下1.11裡jQuery物件究竟長啥樣

jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        // Need init if jQuery is called (just allow error to be thrown if not included)
        return new jQuery.fn.init( selector, context );
}

jQuery物件其實是return了一個它自己的

建構子叫做init,我們再來看一下init做了些什麼

// Initialize a jQuery object
    init = jQuery.fn.init = function( selector, context ) {
        var match, elem;
        // HANDLE: $(""), $(null), $(undefined), $(false)
            //超级省略...下略
        // Handle HTML strings
        // HANDLE: $(html) -> $(array)
        // HANDLE: $(html, props)
        // HANDLE: $(#id)
        // HANDLE: $(expr, $(...))
        // HANDLE: $(expr, context)
        // HANDLE: $(DOMElement)
        // HANDLE: $(function)
        return jQuery.makeArray( selector, this );
    };
// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

從上面的摘取的在程式碼註解中,我們可以看到jq自己的構造函數裡處理了哪些情況,其中包括html標籤名和id的獲取,意味著這兩種獲取是最底層的,此外$()的其他處理都要經過其他的函數,效率上不如上述處理情形。

同時我們也能看到init的原型被賦予了jQuery.fn, 關於jQuery物件的相關內容,有興趣的朋友可以再多去了解一些。

jQ的狀態選擇符,例如:not,:has,:eq存放在

Sizzle.selectors.pseudos裡面

以上是從jQuery應該明白哪些知識?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn