jQuery原始碼解讀之init函式
阿新 • • 發佈:2018-11-22
jQuery的構造方法:
// 直接new了一個物件。同時根據jQuery.fn = jQuery.prototype,jQuery.fn相當於jQuery.prototype。
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context );
},
jQuery.fn.init方法:
init = jQuery.fn.init = function( selector, context, root ) { return jQuery.makeArray( selector, this ); }; init.prototype = jQuery.fn;
// init的原型指向了jQuery.fn,而jQuery.fn=jQuery.prototype即init.prototype=jQuery.prototype
// 根據js原型鏈的知識,我們通過init方法構造出來的物件,能訪問jQuery.prototype物件的方法。
// 當我們使用類似$(xxx)的時候,jquery為我們new了一個物件,並且這個物件的原型鏈指向jQuery.prototype,我們可以直接使用jQuery.prototype上的方法。
原始碼分析:
init = jQuery.fn.init = function( selector, context, root ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) //判斷selector是否為空,是的話,直接返回this,也就是空的jquery物件。 if ( !selector ) { return this; } //定義了root為rootjQuery,這裡的rootjQuery其實就是jQuery( document ),主要用於選擇器為空的時候,用rootjQuery上下文來代替空值,繼續下面的鏈式操作 root = root || rootjQuery; //判斷selector是否為字串、是否為DOM型別、是否是一個function。 // 如果selector為字串,通過正則判斷selector是不是html字串 if ( typeof selector === "string" ) { if ( selector[ 0 ] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { //假設以<>開頭和結尾的字串是HTML並跳過正則表示式檢查 match = [ null, selector, null ]; } else { //通過正則判斷selector是不是html字串 //rquickExpr用來匹配HTML標記和ID表示式 match = rquickExpr.exec( selector ); } //匹配html或確保沒有為#id指定上下文 //selector為html字串 if ( match && ( match[ 1 ] || !context ) ) { // HANDLE: $(html) -> $(array) //match[1]也就是HTML標記是否存在 if ( match[ 1 ] ) { context = context instanceof jQuery ? context[ 0 ] : context; //jquery通過parseHTML(將html字串轉換為dom)和merge(把第二個陣列merge到第一個陣列)方法 //將HTML標記轉化為由jQuery物件包裝的DOM元素,並返回 jQuery.merge( this, jQuery.parseHTML( match[ 1 ], context && context.nodeType ? context.ownerDocument || context : document, true ) ); // HANDLE: $(html, props) if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { //如果可能,將上下文的屬性稱為方法 if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...並以其他方式設定為屬性 } else { this.attr( match, context[ match ] ); } } } return this; // HANDLE: $(#id) //不存在html標記時直接通過match[2]也就是ID去取對應元素 } else { elem = document.getElementById( match[ 2 ] ); if ( elem ) { //將元素直接注入jQuery物件 this[ 0 ] = elem; this.length = 1; } return this; } // HANDLE: $(expr, $(...)) //如果不是html字串,判斷有沒有context //有context的話,使用context呼叫find方法(也就是sizzle) //沒有就是用document為context呼叫find。 } else if ( !context || context.jquery ) { return ( context || root ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(DOMElement) } else if ( selector.nodeType ) { this[ 0 ] = selector; this.length = 1; return this; // HANDLE: $(function) // document ready的縮寫 } else if ( jQuery.isFunction( selector ) ) { return root.ready !== undefined ? root.ready( selector ) : //如果沒有準備就立即執行 selector( jQuery ); } // 處理成jquery陣列,這裡的makeArray對外是將一個類陣列物件轉換為真正的陣列物件,對內有個過載,就是處理成jquery陣列物件。 return jQuery.makeArray( selector, this ); };
參考: