標籤:style io ar color 使用 sp for strong on
先來瞭解幾個jQuery方法:
<li></li>
<li></li>
<li></li>
$("li") -> this -> jQuery對象 -> { 0 : "li", 1 : "li", 2 : "li", length : 3 }
$("<li>aaa") 的效果跟 $("<li>")的效果是一樣的。
然後來看一下init方法,也就是建立jQuery對象調用的方法:
jQuery.fn = jQuery.prototype = {
jquery: core_version, //jQuery的版本
constructor:jQuery, //修正constructor的指向,不寫這個的話,constructor會指向Object,因此你重寫了JQuery的prototype。
//建立一個建構函式時,會自動在建構函式的prototype對象中新添constructor屬性(指向建構函式)。但是為了防止原型對象的覆蓋,比如:Person.prototype = {};這時裡面的constructor指向會出問題,需要修正,Person.prototype = { constructor: Person}
init:function(selector,context,rootjQuery){
var match,elem;
if(!selector){ //處理這種情況:$(""), $(null), $(undefined), $(false)
return this;
}
if ( typeof selector === "string" ) {
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
// $("<li>") -> match = [ null, "<li>", null ];
// $("<li>1</li><li>2</li>") -> match = [ null, "<li>1</li><li>2</li>", null ];
match = [ null, selector, null ];
} else {
// 此正則rquickExpr匹配後,會出現以下幾種情況:
// 1. match = null; $(".box"), $("div"), $("#div1 div.box")
// 2. match = ["#div1",null,"div1"]; $("#div1")
// 3. match = ["<li>aaa","<li>",null]; $("<li>aaa")
match = rquickExpr.exec( selector );
}
// $("#div1")通過id匹配元素,是在document中執行,不會傳入context,所以context為空白,因此進入if語句
if ( match && (match[1] || !context) ) {
if ( match[1] ) { // $("<li>"), $("<li>aaa"),$("<li>1</li><li>2</li>")
//context就是document,因為建立元素只能在document中執行。但是頁面裡面有iframe時,iframe中的document與頁面的document不同,所以$("<li>",document)有第二個參數。一般用不上。
context = context instanceof jQuery ? context[0] : context;
//$("<li>",$(document)),得到原生的document。
jQuery.merge( this, jQuery.parseHTML(match[1],context && context.nodeType ? context.ownerDocument || context : document,
true
) );
//parseHTML方法:第一個參數傳入標籤字串"<li>",第二個參數傳入執行內容document,第三個參數true代表可以建立script標籤"<script><\/script>"(script前面的反斜線需要轉義,其他標籤不需要),false代表不能。傳回值是一個數組:$("<li>") -> ["li"], $("<li>1</li><li>2</li>") ->["li","li"]
//merge方法是把數群組轉換成jQuery對象:["li"] -> {0:"li",length:1} ;["li","li"] -> {0:"li",1:"li",length:2}
rsingleTag匹配單標籤的,$("<li>"),$("<li></li>")
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
//$("<li>",{title:"hi",html:"abcd"}) 針對這種情況的,context 為json對象。
for ( match in context ) {
//如果屬性是jQuery方法,就執行方法
if ( jQuery.isFunction( this[ match ] ) ) {
this[ match ]( context[ match ] );
} else {
//如果不是方法,就設定屬性。
this.attr( match, context[ match ] );
}
}
}
return this;
}
else {
elem = document.getElementById( match[2] );
// Blackberry 4.6:elem存在,但是頁面上沒有,所以添加了elem.parentNode,如果都滿足,則elem一定存在頁面上。
if ( elem && elem.parentNode ) {
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector; //"#div"
return this;
}
}
else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector ); //rootjQuery = $(document)
// 處理這種$(expr, context),context是否是jQuery對象(context.jquery存在就是jQuery對象),會轉換成$(context).find(expr)
//或者$(expr),會轉換成$(document).find(expr)
}
else { //如果context存在,但是不是jQuery對象,就執行
return this.constructor( context ).find( selector ); //建立jQuery對象,並調用find方法
}
}
else if ( selector.nodeType ) { //如果是dom節點,比如:$(document)
this.context = this[0] = selector;
this.length = 1;
return this;
}
else if ( jQuery.isFunction( selector ) ) { //文檔載入有兩種方式:$(function(){});$(document).ready(function(){});
return rootjQuery.ready( selector );
}
if ( selector.selector !== undefined ) { //$($("#div1")),當傳入jQuery對象時
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray( selector, this ); //傳入數組和json對象時,比如:$([]),$({})
//makeArray把selector(類數組)轉換成數組(外部使用),當傳入第二個參數時(內部使用),就會轉換成jQuery對象的形式。
},
length:0, //匹配到的元素的長度,預設為0.
......
};
加油!
jquery源碼解析:jQuery原型方法init的詳解