天天看點

jQuery 2.0.3 源碼分析 回調對象 - Callbacks

jQuery.Callbacks()是在版本1.7中新加入的。它是一個多用途的回調函數清單對象,提供了一種強大的方法來管理回調函數隊列。

那麼jQuery.Callbacks使用場景在哪裡?

在很多時候需要控制一系列的函數順序執行。那麼一般就需要一個隊列函數來處理這個問題

我們看一段代碼

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

傳入一組函數參數,靠遞歸解析,分個執行,其實就是靠setTimeout可以把函數加入到隊列末尾才執行的原理

*****但是這樣寫,是不是很麻煩?*****

我們換成jQuery提供的方式

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

是不是便捷很多了,代碼又很清晰,是以它是一個多用途的回調函數清單對象,提供了一種強大的方法來管理回調函數隊列。

同時還提供幾個便捷的處理參數

<code>once</code>: 確定這個回調清單隻執行( .fire() )一次(像一個遞延 Deferred).

<code>memory</code>: 保持以前的值,将添加到這個清單的後面的最新的值立即執行調用任何回調 (像一個遞延 Deferred).

<code>unique</code>: 確定一次隻能添加一個回調(是以在清單中沒有重複的回調).

<code>stopOnFalse</code>: 當一個回調傳回false 時中斷調用

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

once的作用是使callback隊列隻執行一次

OK,我們大概知道這個是幹嘛用的了,可以開始上正菜了。

根據jQuery.Callbacks()的API

提供一下幾種方法:

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

我們看官網提供的demo

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

可以将上述兩個方法作為回調函數,并添加到 <code>$.Callbacks</code> 清單中,并按下面的順序調用它們:

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

這樣做的結果是,當構造複雜的回調函數清單時,将會變更很簡單。可以根據需要,很方面的就可以向這些回調函數中傳入所需的參數。

上面的例子中,我們使用了 <code>$.Callbacks()</code> 的兩個方法: <code>.add()</code> 和 <code>.fire()</code>。 .add() 可以向回調函數清單中添加新的回調函數,fire() 可以向回調函數中傳遞參數,并執行回調函數。

設計思想:

先看官網的demo這個列子,涉及到了 add 與 fire方法,熟悉設計模式的童鞋呢,一眼就看出,其實又是基于釋出訂閱的觀察者模式的設計了

pub/sub (觀察者模式) 的背後,總的想法是在應用程式中增強松耦合性。并非是在其它對象的方法上的單個對象調用。一個對象作為特定任務或是另一對象的活動的觀察者,并且在這個任務或活動發生時,通知觀察者。觀察者也被叫作訂閱者(Subscriber),它指向被觀察的對象,既被觀察者(Publisher 或 subject)。當事件發生時,被觀察者(Publisher)就會通知觀察者(subscriber)

作為 <code>$.Callbacks()</code> 的建立元件的一個示範,隻使用回調函數清單,就可以實作 Pub/Sub 系統。将 <code>$.Callbacks</code> 作為一個隊列

我來模拟下正常最簡單的實作

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

Observable.add(function() {

  alert(1)

})

Observable.fire(function() {

  alert(2)

Observable.fire(); // 1, 2

jQuery 2.0.3 源碼分析 回調對象 - Callbacks

建構一個存放回調的數組,如this.callbacks= [] 添加回調時,将回調push進this.callbacks,執行則周遊this.callbacks執行回調。

也彈出1跟2了,實際上jQuery.callbacks是如何處理的呢?

我們看源碼

整個$.Callbacks的源碼很少,它是一個工廠函數,使用函數調用(非new,它不是一個類)建立對象,它有一個可選參數flags用來設定回調函數的行為。、

對外的接口也就是self的傳回

jQuery 2.0.3 源碼分析 回調對象 - Callbacks

self上的add源碼

jQuery 2.0.3 源碼分析 回調對象 - Callbacks

源碼

其中有一段代碼要單獨拿出來

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

add方法

callbacks.add( callbacks )

callbacks

一個函數,或者一個函數數組,用來添加到回調清單。

如果是數組會遞歸調用私有的add函數 list.push( arg );

發現沒,設計的原理上其實跟上面發的簡單模式 大同小異

fire方法

外觀模式 self.fire –&gt; self.fireWith –&gt; fire

最終執行代碼是内部私有的fire方法了

jQuery 2.0.3 源碼分析 回調對象 - Callbacks

最終處理的代碼

其實就是拿出list中儲存的回調函數,執行罷了,是以整個設計的原理,還是符合我們開始設想的

具體的實作

<code>$.Callbacks( "once" )</code>

確定這個回調清單隻執行( .fire() )一次(像一個遞延 Deferred).

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

在fire中調用了 self.disable(); 方法

<code>$.Callbacks( "memory" )</code>

保持以前的值,将添加到這個清單的後面的最新的值立即執行調用任何回調 (像一個遞延 Deferred).

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

在調用 add() 方法時,如果這時 callbacks隊列 滿足 fired &amp;&amp; firing = false(真執行完畢) &amp;&amp; memory(需要在構造函數指定),那麼add() 進去的回調函數會立即執行,而這個 add 進去的回調函數調用時的參數存儲在 memory 變量中。memory 變量用于存儲最後一次調用 callbacks.fireWith(...) 時所使用的參數 [context, arguments]。

<code>$.Callbacks( "unique" )</code>

確定一次隻能添加一個回調(是以在清單中沒有重複的回調)

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

****注意add方法預設不去重,比如這裡fn1添加兩次,fire時會觸發兩次****

這裡處理很簡單

在添加的到處理隊列時候,判斷一下即可

<code>$.Callbacks( "stopOnFalse" )</code>:

當一個回調傳回false 時中斷調用

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

附源碼:

jQuery 2.0.3 源碼分析 回調對象 - Callbacks
jQuery 2.0.3 源碼分析 回調對象 - Callbacks

jQuery.Callbacks() 比較簡單,也沒什麼難點

jQuery.Callbacks() 方法的核心是 fire() 方法,将該 fire() 方法作為私有方法被封裝在函數中不可直接通路

是以像 memory、firing、fired 這些狀态對于外部上下文來說是不可更改的

還有需要注意的是,如果回調函數中使用了 this 對象,可以直接用這個 this 來通路self對象的公有API。當然,也可以用 fireWith() 自己指定 this 的引用對象。

jQuery.Callbacks()的核心思想是 Pub/Sub 模式,建立了程式間的松散耦合和高效通信。

本文轉自艾倫 Aaron部落格園部落格,原文連結:http://www.cnblogs.com/aaronjs/p/3342344.html,如需轉載請自行聯系原作者

繼續閱讀