摘要:節點修改對象的屬性,這就相當于把對象轉成了一個類數組,最后返回,可用于鏈式調用。如果傳入的是單標簽,且第二個參數是一個純對象例如則把后面對象的屬性一一添加到創建的這個節點的屬性上。
我們先看看jQuery的原型中初始化了哪些屬性和方法:
jQuery.fn = jQuery.prototype = { jquery: core_version, //jquery版本號 constructor: jQuery, //構造器指向 init: //jquery的入口函數,主要用來實現選擇器和DOM節點的創建 selector: //將選擇器進行存儲 length: //當前選擇器存儲的DOM節點的個數 toArray: //通過方法借調的方式,把一個類數組對象轉換為一個數組 //類數組對象就是指有數字作為屬性,且有length屬性,jQuery是一個類數組對象,arguments也是。 get: //獲取jQuery對象中的某一個DOM節點,返回的是一個DOM節點, pushStack: //將一個DOM元素集合加入到jQuery對象的prevObject中。 //this.prevObject=this,讓當前DOM集合存儲到prevObject屬性中,方便end()調用是回溯。 each: //對數組進行遍歷 ready: //當DOM樹加載完畢后,回調該函數 slice: //類似于toArray方法,只是該方法會進行一次pushStack操作 first: //返回第一個元素的jQuery對象 last: //返回最后一個元素的jQuery對象 eq: //傳入一個數字num,獲取第num個元素的jQuery對象 map: //map將一個數組中的元素轉換到另一個數組中,可以傳入一個回調函數,作用與each類似,只是map會返回一個新的數組,而each不會 end: //返回調用parent()、find()、filter()等方法之前的jQuery對象,就是回溯到上一個DOM合集 push: core_push, //存儲了數組的push方法 sort: [].sort, //存儲了數組的sort方法 splice: [].splice //存儲了數組的splice方法 }
上面是對jQuery初始化的一些方法和屬性的介紹,前面初始化jQuery對象時,我們可以看到jQuery對象其實是一個實例化的jQuery.fn.init,所以這里主要看下init是如何實現,其余的方法在具體用到的時候再看。
首先可以觀察到init方法傳入了三個參數:
init: function( selector, context, rootjQuery ) {...}
selector(選擇器)
context(上下文環境)
rootJQuery( $(document) )
rootjQuery = jQuery(document);//參見866行
init對傳入的選擇器進行了以下的區分:
空 : 包括 "" false undefined null
if ( !selector ) {return this;}
string:這個部分判斷有點復雜,會在后面詳細的介紹。
if ( typeof selector === "string" )...
DOM節點:修改jQuery對象的屬性 0:selector,length:1 ;這就相當于把jQuery對象轉成了一個類數組,最后返回this,可用于鏈式調用。
if ( selector.nodeType ){//通過判斷該變量是否有nodeType屬性來確定是不是一個DOM節點
this.context = this[0] = selector;
this.length = 1;
return this;}
Function: $(fn) 就相當于 $(document).ready(fn)
if ( jQuery.isFunction( selector ){//jquery內部用來判斷一個對象是不是一個函數的方法 return rootjQuery.ready( selector );}
jQuery對象:
if ( selector.selector !== undefined ) {//如果改變了有select屬性則認為該變量是jQ變量 this.selector = selector.selector; this.context = selector.context; return jQuery.makeArray( selector, this );}
其他任意類型的值:將傳入的變量和jQuery對象合并成一個數組
return jQuery.makeArray( selector, this );
下面我們來看當 selector 為一個字符串時是如何進行處理的:
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {//匹配單標簽 match = [ null, selector, null ]; } else { match = rquickExpr.exec( selector ); } if ( match && (match[1] || !context) ) { //如果是字符串是html標簽 if ( match[1] ) { jQuery.merge( this, jQuery.parseHTML(match[1]) ); //先通過parseHTML將字符串轉換成DOM對象的數組,然后通過merge將DOM對象的數組合并到this上。 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { 如果傳入的是單標簽,且第二個參數是一個純對象,例如: $("",{"id":"box", "class":"red"})//則把后面對象的屬性一一添加到創建的這個DOM節點的屬性上。 //現在知道了通過$不僅可以創建標簽,還能在創建單標簽的時候直接在后面寫屬性。 } } else { //如果是"#id",直接通過js的原生方法getElementById獲取DOM節點 elem = document.getElementById( match[2] ); } //后面的情況都是通過find方法來找復雜的選擇器。例如selector是一個".ClassName" //具體過程為jQuery.fn.find->jQuery.find->Sizzle //最后會調用Sizzle方法,這是jQuery選擇器的核心方法,是一個獨立的引擎,等到了后面我看懂了再告訴大家吧 (逃 } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); } else { return this.constructor( context ).find( selector ); }看這段代碼前我們要先弄懂match到底是什么東西
rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]*))$/; (75行) match = rquickExpr.exec( selector ); (116行)exec方法用于正則匹配,返回一個數組,第一個元素是匹配到的字符串,后面的元素為匹配子項,具體用法。
舉個栗子:
var rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]*))$/; console.log( match = rquickExpr.exec( "" ) ); // ["
", "
", undefined] console.log( match = rquickExpr.exec( "#id" ) ); // ["#id", undefined, "id"]
現在我們知道了,match其實就是存儲了字符串含義的數組,不得不感嘆這是人想出來的嗎。正則懵逼。
如果match[1]存在就代表是html標簽
如果match[2]存在就代表是id名
如果兩種情況都沒有匹配到的話,表示這是一個復雜選擇器,具體的實現是jQuery內部的Sizzle方法來實現,這個方法有兩千行左右,可謂是jQuery的核心,而且jQuery把這個方法也當成了一個多帶帶的庫,如果覺得jQuery太大,只會用到選擇器部分的功能,感興趣的話可以在Sizzle官網 下載
可以看到我們平時調用 $() 的時候很爽,又能當選擇器又能創節點,但是不知道這后面的實現方法原來這么復雜,還真是用起來越方便的東西實現越復雜。
恩,樓上說的對 -。-
感興趣的話可以看看我的github,不妨給個star。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/86700.html
摘要:的緩存機制來看看中提高的數據緩存機制,有兩個函數,分別是和,可以看出來,一個是在對象上,一個是在生成的對象上。而且從源碼來看,的緩存機制自帶清內存操作,更是錦上添花呀。參考源碼分析數據緩存本文在上的源碼地址,歡迎來。 歡迎來我的專欄查看系列文章。 不打算介紹 deferred,或者放到后面以后去介紹,因為我對于 js 的異步存在著恐懼,看了半天代碼,發現,用挺好用的,一看源碼,全傻眼了...
摘要:的指向的是對象,所以此時擴展的是對象,可以直接通過的方式調用。 寫過jquery插件的人都知道可以通過jquery提供的extend可以對jquery對象進行擴展,而且該方法不僅可以對jquery對象擴展,還能給一個對象添加新的屬性和方法,這個在后面會介紹。 通過不同的方式調用extend擴展的方法也不同: 通過 $.extend() 擴展的是靜態方法; 而通過 $.fn.exten...
摘要:而在構造函數中,返回了的實例對象。在中直接返回過的實例,這里的是的真正構造函數最后對外暴露入口時,將字符與對等起來。因此當我們直接使用創建一個對象時,實際上是創建了一個的實例,這里的正真構造函數是原型中的方法。 showImg(https://segmentfault.com/img/remote/1460000008749398); 早幾年學習前端,大家都非常熱衷于研究jQuery源...
摘要:到目前為止,的貢獻者團隊共名成員,多條,可想而知,是一個多么龐大的項目。參考源碼分析整體架構源碼解析讀書筆記第二章構造對象函數詳解本文在上的源碼地址,歡迎來。 歡迎來我的專欄查看系列文章。 決定你走多遠的是基礎,jQuery 源碼分析,向長者膜拜! 我雖然接觸 jQuery 很久了,但也只是局限于表面使用的層次,碰到一些問題,找到 jQuery 的解決辦法,然后使用。顯然,這種做法的...
摘要:本來想學習一下的源碼,但由于的源碼有多行,設計相當復雜,所以決定從開始,分析一個成熟的框架的代碼結構及執行步驟。同時發表在我的博客源碼分析代碼結構 本來想學習一下jQuery的源碼,但由于jQuery的源碼有10000多行,設計相當復雜,所以決定從zepto開始,分析一個成熟的框架的代碼結構及執行步驟。 網上也有很多zepto的源碼分析,有的給源碼添加注釋,有的談與jQuery的不同,...
閱讀 3206·2021-09-06 15:02
閱讀 2253·2019-08-30 15:48
閱讀 3449·2019-08-29 11:08
閱讀 3292·2019-08-26 13:55
閱讀 2455·2019-08-26 13:35
閱讀 3169·2019-08-26 12:11
閱讀 2609·2019-08-26 11:48
閱讀 893·2019-08-26 11:42