摘要:在對(duì)象的內(nèi)部,有著一個(gè)對(duì)象棧,用來(lái)維護(hù)所有已經(jīng)操作過(guò)的對(duì)象。這樣來(lái)想一想,如果每一個(gè)對(duì)象都有一個(gè)指針指向上一個(gè)對(duì)象的話,也就間接組成了一個(gè)對(duì)象棧。
歡迎來(lái)我的專(zhuān)欄查看系列文章。
學(xué)習(xí)了 prevObject 之后發(fā)現(xiàn),我之前寫(xiě)的一篇博客介紹 pushStack 函數(shù)那個(gè)內(nèi)容是有問(wèn)題的。本來(lái)我以為這個(gè) pushStack 函數(shù)就是一個(gè)普通的函數(shù),它接受一個(gè) DOM (數(shù)組)參數(shù),把該參數(shù)合并到一個(gè) jQuery 對(duì)象中并返回該 jQuery 對(duì)象。
后來(lái)我也疑惑過(guò)一段時(shí)間,為什么看不到這個(gè)函數(shù)的使用,而且為什么要把它放到 jQuery.fn 上,直到今天,才恍然大悟。
jQuery 的 prevObject 對(duì)象當(dāng)我們新建一個(gè) jQuery 對(duì)象的時(shí)候,都會(huì)在其屬性中發(fā)現(xiàn)一個(gè) prevObject 的屬性,如果單單從名字來(lái)看的,“前一個(gè)對(duì)象”,那么它到底是怎么用的呢。
在 jQuery 對(duì)象的內(nèi)部,有著一個(gè) jQuery 對(duì)象棧,用來(lái)維護(hù)所有已經(jīng)操作過(guò)的 jQuery 對(duì)象。這樣子的話可以寫(xiě)出很流暢的 jQuery 代碼,比如操作父元素,操作子元素,再回到父元素的時(shí)候就很方便。
但實(shí)際上,這個(gè)棧是不存在的,我們知道數(shù)組可以當(dāng)作?;蜿?duì)列來(lái)使用,是不是說(shuō) jQuery 內(nèi)部有這么個(gè)數(shù)組來(lái)存放這個(gè)對(duì)象棧呢。答案是 no,為什么,因?yàn)闆](méi)必要這么麻煩。這樣來(lái)想一想,如果每一個(gè) jQuery 對(duì)象都有一個(gè)指針指向上一個(gè)對(duì)象的話,也就間接組成了一個(gè) jQuery 對(duì)象棧。如果棧只有一個(gè)元素,prevObject 就默認(rèn)指向 document。prevObject 是干什么用的,就是來(lái)實(shí)現(xiàn)對(duì)象棧的。比如:
標(biāo)題
container
重點(diǎn)
對(duì)于上面的 html:
var $view = $("#view"); // $header 是由 $view 操作得到的 var $header = $view.find(".header"); $header.prevObject === $view; // true
不過(guò)在使用的時(shí)候,都是忽略對(duì)象棧而定義不同的 jQuery 對(duì)象來(lái)指向父元素和子元素,就像上面的例子那樣,既然定義了 $view 和 $header,就不需要 prevObject 了。
jQuery.fn.end 和 jQuery.fn.addBack這兩個(gè)函數(shù)其實(shí)就是 prevObject 的應(yīng)用,舉個(gè)例子就能弄明白了,仍然是上面的那個(gè) html:
$("#view").find(".header").css({"color": "red"}) .end() .find(".espe").css({"color": "white"})
加了 end之后,當(dāng)前執(zhí)行的 jQuery 對(duì)象就變成 $("#view")了,所以可以繼續(xù)執(zhí)行 find 操作等等,如果不加的話,這段話是不能執(zhí)行成功的??梢?jiàn),如果這樣子寫(xiě) jQuery 不僅寫(xiě)法優(yōu)雅,而且還很高效。
end 和 addBack 是有區(qū)別的,end() 函數(shù)只是單純的進(jìn)行出棧操作,并返回出棧的這個(gè) jQuery 對(duì)象,而 addBack() 函數(shù)不會(huì)執(zhí)行出棧,而是把棧頂對(duì)象和當(dāng)前的對(duì)象組成一個(gè)新對(duì)象,入棧:
$("#view").find(".header").nextAll() .addBack() .css({"color": "red"}) // 顏色全紅
上面的代碼,會(huì)使得 #view 的三個(gè)子元素的顏色都設(shè)置為紅色。
相關(guān)函數(shù)源碼重新來(lái)看下 pushStack 函數(shù)吧,這個(gè)函數(shù)不僅在 fn.find() 函數(shù)中出現(xiàn),好多涉及 jQuery dom 操作的原型函數(shù)都出現(xiàn)了,而且之前介紹的時(shí)候,忽略了一個(gè)重要的部分 prevObject 對(duì)象:
jQuery.fn.pushStack = function (elems) { // 將 elems 合并到 jQuery 對(duì)象中 var ret = jQuery.merge(this.constructor(), elems); // 實(shí)現(xiàn)對(duì)象棧 ret.prevObject = this; // 返回 return ret; }
pushStack 生成了一個(gè)新 jQuery 對(duì)象 ret,ret 的 prevObject 屬性是指向調(diào)用 pushStack 函數(shù)的那個(gè) jQuery 對(duì)象的,這樣就形成了一個(gè)棧鏈,其它原型方法如 find、nextAll、filter 等都可以調(diào)用 pushStack 函數(shù),返回一個(gè)新的 jQuery 對(duì)象并維持對(duì)象棧。
我們知道了所有 jQuery 方法都有一個(gè) prevObject 屬性的情況下,來(lái)看看 end 方法:
jQuery.fn.end = function () { return this.prevObject || this.constructor(); }
還有 addBack 方法:
jQuery.fn.addBack = function (selector) { // 可以看出有參數(shù)的 addBack 會(huì)對(duì) prevObject 進(jìn)行過(guò)濾 return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector)); }
里面穿插了一個(gè) fn.add 方法:
jQuery.fn.add = function (selector, context) { return this.pushStack( jQuery.uniqueSort( jQuery.merge(this.get(), jQuery(selector, context)))); }
應(yīng)該不需要解釋吧,源碼一清二楚。
總結(jié)我之前就已經(jīng)說(shuō)過(guò),很少會(huì)使用 end 或 pushStack 方法,而在 jQuery 內(nèi)部的原型方法中,比如 find、nextAll、filter 等,被頻繁使用,這種封裝一個(gè) jQuery 的方法很棒,會(huì)把對(duì)象棧給維護(hù)得很好。無(wú)論如何,這就是 jQuery 的魅力吧!
參考jQuery 2.0.3 源碼分析 回溯魔法 end()和pushStack()
jQuery API .end()
jQuery API .addBack()
本文在 github 上的源碼地址,歡迎來(lái) star。
歡迎來(lái)我的博客交流。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81701.html
摘要:用來(lái)存放每一個(gè)可能的結(jié)果最終結(jié)果深度優(yōu)先遍歷剪枝當(dāng)遍歷到底個(gè)數(shù)是,如果的元素個(gè)數(shù)剩余元素個(gè)數(shù)時(shí),就不滿足條件了中元素個(gè)數(shù)達(dá)到,表示深度優(yōu)先遍歷到達(dá)最深處了。 ?77. 組合77. 組合77. 組合 給定兩個(gè)整數(shù)?n?和?k,返回范圍?[1, n]?中所有可能的?k?個(gè)數(shù)的組合。 你可以按?任...
摘要:忍者級(jí)別的函數(shù)操作對(duì)于什么是匿名函數(shù),這里就不做過(guò)多介紹了。我們需要知道的是,對(duì)于而言,匿名函數(shù)是一個(gè)很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個(gè)供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...
摘要:事件機(jī)制在講事件機(jī)制之前呢我們有一個(gè)很重要的東西要先講那就是如何實(shí)現(xiàn)事件委托代理只有必須先明白了如何實(shí)現(xiàn)一個(gè)事件委托我們才能更好的去實(shí)現(xiàn)和在我看來(lái)和里最難實(shí)現(xiàn)的就是他的事件委托以上是我對(duì)整個(gè)委托的實(shí)現(xiàn)當(dāng)然在這只做了非常簡(jiǎn)單的實(shí)現(xiàn)沒(méi)有對(duì)很多 Lesson-8 事件機(jī)制 在講事件機(jī)制之前呢,我們有一個(gè)很重要的東西要先講,那就是如何實(shí)現(xiàn)事件委托(代理). 只有必須先明白了如何實(shí)現(xiàn)一個(gè)事件委...
摘要:事件機(jī)制在講事件機(jī)制之前呢我們有一個(gè)很重要的東西要先講那就是如何實(shí)現(xiàn)事件委托代理只有必須先明白了如何實(shí)現(xiàn)一個(gè)事件委托我們才能更好的去實(shí)現(xiàn)和在我看來(lái)和里最難實(shí)現(xiàn)的就是他的事件委托以上是我對(duì)整個(gè)委托的實(shí)現(xiàn)當(dāng)然在這只做了非常簡(jiǎn)單的實(shí)現(xiàn)沒(méi)有對(duì)很多 Lesson-8 事件機(jī)制 在講事件機(jī)制之前呢,我們有一個(gè)很重要的東西要先講,那就是如何實(shí)現(xiàn)事件委托(代理). 只有必須先明白了如何實(shí)現(xiàn)一個(gè)事件委...
閱讀 1969·2021-11-24 09:39
閱讀 3357·2021-09-22 14:58
閱讀 1198·2019-08-30 15:54
閱讀 3349·2019-08-29 11:33
閱讀 1817·2019-08-26 13:54
閱讀 1628·2019-08-26 13:35
閱讀 2497·2019-08-23 18:14
閱讀 801·2019-08-23 17:04