大多數(shù)jQueryDOM遍歷方法來操作jQuery對(duì)象實(shí)例,并創(chuàng)建一個(gè)新的對(duì)象,匹配一個(gè)不同的DOM元素集合。當(dāng)發(fā)生這種情況時(shí),實(shí)際上是新的元素集合被壓入到對(duì)象內(nèi)部維護(hù)的棧中。每次過濾方法都會(huì)被壓入棧中。當(dāng)我們需要返回到前一個(gè)狀態(tài)時(shí),我們可以使用end()進(jìn)行出棧操作,來返回棧中的前一個(gè)狀態(tài)。
假設(shè)頁面上有幾個(gè)列表項(xiàng):右圖所示
end()方法主要用于jQuery的鏈?zhǔn)綄傩灾?。?dāng)沒有使用鏈?zhǔn)接梅〞r(shí),我們通常只是調(diào)用變量名上的前一個(gè)對(duì)象,所以我們不需要操作棧。
使用end()時(shí),我們可以一次性調(diào)用所有需要的方法:
$('ul.first').find('.foo').css('background-color', 'red').end().find('.bar').css('background-color', 'green');
鏈?zhǔn)降脑砭褪且祷禺?dāng)前操作的上下文。
下面的代碼是錯(cuò)誤的:
$('ul.first').find('.foo').css('background-color', 'red').find('.bar').css('background-color', 'green');
上面的代碼因?yàn)樯舷挛谋磺袚Q了,所以執(zhí)行find(‘bar’)時(shí)就出錯(cuò)了。
下面的代碼是正確的寫法:
$('ul.first').find('.foo').css('background-color', 'red').end().find('.bar').css('background-color', 'green');
首先在鏈?zhǔn)接梅ㄖ兄辉诘谝粋€(gè)列表中查找樣式為 foo 的項(xiàng)目,并將其背景色變成紅色。然后end()返回調(diào)用find()之前的狀態(tài)。因此,第二次 find() 將只會(huì)查找 <ul class="first"> 中的 '.bar',而不是繼續(xù)在<li class="foo">中進(jìn)行查找,結(jié)果是將匹配到的元素的背景色變成綠色。上述代碼的最終結(jié)果是:第一個(gè)列表中的第 1 和第 3 個(gè)列表項(xiàng)的背景色有顏色,而第二個(gè)列表中的任何項(xiàng)目都沒有背景色。
總的來說:end方法就是回溯到上一個(gè)Dom合集,因此對(duì)于鏈?zhǔn)讲僮髋c優(yōu)化,這個(gè)方法還是很有意義的。
源碼實(shí)現(xiàn)
既然是回溯到上一個(gè)DOM合集,那么肯定end方法中返回的就是一個(gè)jQuery對(duì)象了,所以我們看源碼其實(shí)就是返回prevObject對(duì)象了,如下代碼:
end: function() {
return this.prevObject || this.constructor(null);
}
prevObject在什么情況下會(huì)產(chǎn)生?
在構(gòu)建jQuery對(duì)象的時(shí)候,通過pushStack方法構(gòu)建,如下代碼:
jQuery.fn.extend({ find: function(selector) { //...........................省略................................ //通過sizzle選擇器,返回結(jié)果集 jQuery.find(selector, self[i], ret); // Needed because $( selector, context ) becomes $( context ).find( selector ) ret = this.pushStack(len > 1 ? jQuery.unique(ret) : ret); ret.selector = this.selector ? this.selector + " " + selector : selector; return ret; } }
可以看到通過jQuery.find后得到了結(jié)果ret這個(gè)就是通過純的DOM節(jié)點(diǎn),那么如果變成一個(gè)jQuery對(duì)象呢?
接著我們看pushStack對(duì)象,作用就通過新的DOM元素去創(chuàng)建一個(gè)新的jQuery對(duì)象
pushStack: function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; // Return the newly-formed element set return ret; }
流程解析:
1、首先構(gòu)建一個(gè)新的jQuery對(duì)象,因?yàn)閏onstructor是指向構(gòu)造器的,所以這里就等同于調(diào)用jQuery()方法了,返回了一個(gè)新的jQuery對(duì)象;
2、然后用jQuery.merge語句把elems節(jié)點(diǎn)合并到新的jQuery對(duì)象上;
3、最后給返回的新jQuery對(duì)象添加prevObject屬性,我們看到prevObject其實(shí)還是當(dāng)前jQuery的一個(gè)引用罷了,所以也就是為什么通過prevObject能取到上一個(gè)合集的原因了。
請(qǐng)驗(yàn)證,完成請(qǐng)求
由于請(qǐng)求次數(shù)過多,請(qǐng)先驗(yàn)證,完成再次請(qǐng)求
打開微信掃碼自動(dòng)綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報(bào)