摘要:最近想看一下源碼,搜到了這樣一篇博客從源碼學(xué)到的件事情本文基于這篇視頻博客,提煉了一些內(nèi)容,分享給大家。的狀態(tài)選擇符,比如存放在里面
最近想看一下jQuery源碼,搜到了這樣一篇博客《從jQuery源碼學(xué)到的10件事情》
http://www.paulirish.com/2010/10-things-i-learned-from-the-jquery-source/
本文基于這篇視頻博客,提煉了一些內(nèi)容,分享給大家。
說(shuō)明:
這篇文章寫(xiě)于2010年,作者在視頻里使用的是jQuery 1.4版本,我根據(jù)視頻里講到的內(nèi)容,對(duì)應(yīng)目前的1字頭1.11版本做了一些調(diào)整,一些被拋棄或者被移除的內(nèi)容頁(yè)做了刪減,并在此感謝原作者h(yuǎn)ttps://github.com/paulirish
黑箱系統(tǒng)的概念是給定輸入返回輸出的一個(gè)系統(tǒng),黑箱把實(shí)現(xiàn)過(guò)程進(jìn)行封裝。這里說(shuō)的jQuery黑箱是為js全局變量window輸出jQuery 和 $,而過(guò)程被封裝到黑箱里,與外界互不干擾。
jQuery 1.4版本的黑箱是利用了類(lèi)似如下的自執(zhí)行函數(shù)
(function( window, undefined){})(window)
作者給了一個(gè)比較通用的實(shí)現(xiàn)黑箱的方法
undefined = true; (function(window, document, undefined){ if(foo == undefined) { } })(this, document)
jQuery的黑箱里多傳了第三個(gè)形參叫做undefined,而傳實(shí)參的時(shí)候并沒(méi)有傳值,js里沒(méi)有傳值的形參會(huì)被設(shè)置為undefined,保證了黑箱內(nèi)部undefined的正確性。js中,undefined作為一個(gè)全局屬性,是可以被賦值的,比如上述代碼中的undefined = true;
以自執(zhí)行函數(shù)的模式實(shí)現(xiàn)黑箱的另外一個(gè)好處是利于壓縮,比如下述的情況,我們只需要在黑箱內(nèi)部使用簡(jiǎn)單的變量。
(function(A, B, C)){ B.getElementById("") })(this, document)
作者為匿名函數(shù)自執(zhí)行舉了很多例子,比如下面這個(gè),為頁(yè)面的某一部分不停地更新(以及不斷地執(zhí)行)
(function loop(){ doStuff(); $("#update").load("awesomething.php",function(){ loop(); }) //setTimeout(loop, 100) })()
jQuery 1.11版本的黑箱采用了全新的工廠方法,本文不探究
noConflict的實(shí)現(xiàn)這個(gè)函數(shù)的差異不大,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; };
我們可以看到防沖突的實(shí)現(xiàn)是先把之前的JQuery 和 $ 存起來(lái),noConflict被調(diào)用的時(shí)候,再還給它們
與原生js屬性命名的轉(zhuǎn)換1.4版本用的是props對(duì)象來(lái)存放jquery對(duì)屬性操作與原生js屬性操作的對(duì)應(yīng)關(guān)系
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 這個(gè)對(duì)象是存放對(duì)應(yīng)關(guān)系表的,比如class轉(zhuǎn)換成className,prop函數(shù)負(fù)責(zé)處理這個(gè)關(guān)系表。
而下面的each很有意思,遍歷數(shù)組中那些屬性,然后把他們小寫(xiě)格式對(duì)應(yīng)到自己,放到 propFix
我們知道在jQuery里一些動(dòng)畫(huà)我們可以直接通過(guò)normal,fast,slow 來(lái)定義實(shí)現(xiàn)速度,這個(gè)在源碼里是這樣定義的
jQuery.fx.speeds = { slow: 600, fast: 200, // Default speed _default: 400 };
調(diào)皮的原作者做了這樣一些事情:
var isIE //... jQuery.fx.speeds._default = isIE ? 800 : 400 jQuery.fx.speeds.veryfast = 200; $("...").fadeIn("veryfast")
一種是可以對(duì)default屬性做條件判斷,還有一種自定義速度,比如"veryfast"
.readyready函數(shù) 1.11版本和1.4版本有較大的差距,新版中很多東西我也不太能理解,我們就簡(jiǎn)單的把核心拿出來(lái)看一下
jQuery.ready.promise = function( obj ) { //...省略若干 } else if ( document.addEventListener ) { // 使用addEventListener "DOMContentLoaded" 監(jiān)聽(tīng)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去做確保載入完成的工作,重點(diǎn)是
document.addEventListener( "DOMContentLoaded", completed, false );
window.addEventListener( "load", completed, false );
document.attachEvent( "onreadystatechange", completed );
window.attachEvent( "onload", completed );
兼容性考量的四種檢查方式
其中從top開(kāi)始,做了一件事情就是IE下面,dom節(jié)點(diǎn)判斷是否有scroll,在IE下如果dom有scroll,沒(méi)有scroll到的元素對(duì)ready會(huì)有影響,這里面我的理解不夠,總之jQuery里用到了一個(gè)叫做Diego Perini的技巧,可以在注釋里的地址看到更多內(nèi)容。
選擇器$("#id").find("tag.thing") --- faster $("#id tag.thing") ------- using sizzle
原作者在這里說(shuō)了一個(gè)jquery效率的問(wèn)題,上面的方法更快一些,而下面的方法稍微慢,簡(jiǎn)單地說(shuō)是因?yàn)橄旅娴姆椒ㄕ{(diào)用了sizzle,通過(guò)sizzle其實(shí)轉(zhuǎn)換成上述的模式,而id的調(diào)用則是直接過(guò)jQuery.init.
這里需要擴(kuò)展一下,我們來(lái)看一下1.11里jQuery對(duì)象究竟長(zhǎng)啥樣
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對(duì)象其實(shí)是return了一個(gè)它自己的構(gòu)造函數(shù)叫做init,我們?cè)賮?lái)看一下init做了些什么
// Initialize a jQuery object init = jQuery.fn.init = function( selector, context ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) //超級(jí)省略...下略 // 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;
從上面的摘取的代碼注釋中,我們可以看到j(luò)q自己的構(gòu)造函數(shù)里處理了哪些情況,其中包括html標(biāo)簽名和id的獲取,意味著這兩種獲取是最底層的,此外$()的其他處理都要經(jīng)過(guò)其他的函數(shù),效率上不如上述處理情況。
同時(shí)我們也能看到init的原型被賦予了jQuery.fn, 關(guān)于jQuery對(duì)象的相關(guān)內(nèi)容,感興趣的朋友可以再多去了解一些。
jQ的狀態(tài)選擇符,比如:not,:has,:eq存放在
Sizzle.selectors.pseudos里面
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78104.html
摘要:目前正在廣泛使用的框架之一就是。是一系列使用編寫(xiě)的自定義控件,用于創(chuàng)建快速響應(yīng)式的和可擴(kuò)展的控件。的組件主要是使用,并提供了交互式,動(dòng)態(tài)和高度可定制的小部件。例如,演示了如何使用自定義控件,嵌套面板和其它元素。 在建立Web應(yīng)用時(shí),通常都需要用到一些有用的UI組件。無(wú)論應(yīng)用中需要的是日歷,滑塊,圖形或其它用于提升或簡(jiǎn)化用戶交互的組件,那么都面臨兩種選擇:要么自己來(lái)創(chuàng)建這些組件,要么使用...
摘要:計(jì)算數(shù)組的極值微信面試題獲取元素的最終前端掘金一題目用代碼求出頁(yè)面上一個(gè)元素的最終的,不考慮瀏覽器,不考慮元素情況。 Excuse me?這個(gè)前端面試在搞事! - 前端 - 掘金金三銀四搞事季,前端這個(gè)近年的熱門(mén)領(lǐng)域,搞事氣氛特別強(qiáng)烈,我朋友小偉最近就在瘋狂面試,遇到了許多有趣的面試官,有趣的面試題,我來(lái)幫這個(gè)搞事 boy 轉(zhuǎn)述一下。 以下是我一個(gè)朋友的故事,真的不是我。 ... ja...
摘要:由于系統(tǒng)變得越來(lái)越復(fù)雜,人們提出了稱(chēng)為預(yù)處理器和后處理器的工具來(lái)管理復(fù)雜性。后處理器在由預(yù)處理器手寫(xiě)或編譯后對(duì)應(yīng)用更改。我之前建議的文章,,也涵蓋了預(yù)處理器相關(guān)的知識(shí)。 譯者:前端小智 原文:medium.freecodecamp.org/from-zero-t… medium.freecodecamp.org/from-zero-t… 我記得我剛開(kāi)始學(xué)習(xí)前端開(kāi)發(fā)的時(shí)候。我看到了很多文章及...
摘要:能不能支持?jǐn)?shù)據(jù)丟失啊可以的,參考我們之前說(shuō)的那個(gè)數(shù)據(jù)零丟失方案其實(shí)一個(gè)肯定是很復(fù)雜的,其實(shí)這是個(gè)開(kāi)放題,就是看看你有沒(méi)有從架構(gòu)角度整體構(gòu)思和設(shè)計(jì)的思維以及能力。其實(shí)回答這類(lèi)問(wèn)題,說(shuō)白了,起碼不求你看過(guò)那技術(shù)的源碼,起碼你大概知道那個(gè)技術(shù)的基本原理,核心組成部分,基本架構(gòu)構(gòu)成,然后參照一些開(kāi)源的技術(shù)把一個(gè)系統(tǒng)設(shè)計(jì)出來(lái)的思路說(shuō)一下就好 比如說(shuō)這個(gè)消息隊(duì)列系統(tǒng),我們來(lái)從以下幾個(gè)角度來(lái)考慮一下 (1...
摘要:這個(gè)是類(lèi)似的一種結(jié)構(gòu),這個(gè)一般就是可以將結(jié)構(gòu)化的數(shù)據(jù),比如一個(gè)對(duì)象前提是這個(gè)對(duì)象沒(méi)嵌套其他的對(duì)象給緩存在里,然后每次讀寫(xiě)緩存的時(shí)候,可以就操作里的某個(gè)字段。 1.string 這是最基本的類(lèi)型了,就是普通的set和get,做簡(jiǎn)單的kv緩存。 2.hash 這個(gè)是類(lèi)似map的一種結(jié)構(gòu),這個(gè)一般就是可以將結(jié)構(gòu)化的數(shù)據(jù),比如一個(gè)對(duì)象(前提是這個(gè)對(duì)象沒(méi)嵌套其他的對(duì)象)給緩存在redis里,然后每次...
閱讀 646·2021-09-22 10:02
閱讀 6410·2021-09-03 10:49
閱讀 571·2021-09-02 09:47
閱讀 2157·2019-08-30 15:53
閱讀 2936·2019-08-30 15:44
閱讀 908·2019-08-30 13:20
閱讀 1822·2019-08-29 16:32
閱讀 895·2019-08-29 12:46