// 初始化jQuery對象,即jQuery.fn.init對象
// @param selector 選擇器,可能是DOM對象、html字符串、jQuery對象、函數或其他任意值。
// @param context 選擇器選擇的范圍
// @param rootjQuery == $(document);
init: function( selector, context, rootjQuery ) {
var match, elem;
//如果selector是""、null、undefined、false,則返回this,這里的this指針指向init對象
//如果在一個函數前面帶上new來調用該函數,那么將創建一個隱藏連接到該函數的prototype成員的新對象,同時this將被綁定到那個新對象上。
if ( !selector ) {
return this;
}
// 如果selector 是String類型,走該分支進行處理
if ( typeof selector === "string" ) {
// 如果selector的第一個字符是“<”並且最后一個字符是">",並且長度大於3
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
// 將html儲存入match數組中,並與另一個分支中的正則捕獲相對應
// 如果走這個分支則說明選擇器為<a>這種形式,則跳過使用正則匹配,不全都使用正則匹配的原因是,可能返回空。
match = [ null, selector, null ];
} else {
// rquickExpr 是在閉包中定義的局部變量,匹配得到的數組類似於:[全匹配, <tag>, #id]
match = rquickExpr.exec( selector );
}
// 如果match不為空,並且match[1]也就是<tag>存在或者context不存在??
if ( match && (match[1] || !context) ) {
// 如果是<tag>的形式
if ( match[1] ) {
// 如果context是jQuery對象,則取其中的第一個DOM元素作為context
context = context instanceof jQuery ? context[0] : context;
// 將通過parseHTML處理生成的DOM對象merge進jQuery對象
jQuery.merge( this, jQuery.parseHTML(
match[1],
//如果context存在並且是note節點,則context就是的頂級節點或自身,否則content=document
context && context.nodeType ? context.ownerDocument || context : document,
true
) );
// isPlainObject DOM節點和window不是純對象
// rsingleTag 匹配一個獨立的標簽,例如<div></div> 或者 <div>
// 這個分支沒讀懂
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;
//如果是#id的形式,走這個分支進行處理
} else {
//通過getEle方法獲得DOM對象 將match[2]傳入,是因為#id的形式是在第二個捕獲組里面儲存的。
elem = document.getElementById( match[2] );
// 如果該id元素存在並且該元素有父節點(判斷父節點的原因是??)
if ( elem && elem.parentNode ) {
// 將該元素保存進jQuery對象數組當中,並設置其length值為1
this.length = 1;
this[0] = elem;
}
// 將jQuery的context屬性設置為document,selector屬性設置為selector
this.context = document;
this.selector = selector;
// 返回生成的jQuery對象
return this;
}
//如果context不存在或者context是jQuery對象 //通過檢測是不是有jquery屬性
} else if ( !context || context.jquery ) {
// 進入Sizzle進行處理(復雜的選擇器)
return ( context || rootjQuery ).find( selector );
//context存在並且context不是jQuery對象的情況 先調用$(context),在進入Sizzle進行處理
} else {
return this.constructor( context ).find( selector );
}
//如果selector不是String,是DOM元素
} else if ( selector.nodeType ) {
//直接將DOM元素存入jQuery對象並設置context和length
this.context = this[0] = selector;
this.length = 1;
return this;
//此分支是為了簡化$(document).ready(function(){});
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
//此處為什么不走else if?而是單獨判斷?
//如果selector是jQuery對象,則設置新jQuery對象的selector和context和原對象的一致。
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
//為最后一個if返回值。
return jQuery.makeArray( selector, this );
},