讀jQuery之十九(多用途回呼函數列表對象)

來源:互聯網
上載者:User

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

整個$.Callbacks的源碼不到200行,它是一個工廠函數,使用函數調用方式(非new,它不是一個類)建立對象,它有一個選擇性參數flags用來設定回呼函數的行為。

$.Callbacks是在jQuery內部使用,如為$.ajax,$.Deferred等組件提供基礎功能的函數。它也可以用在類似功能的一些組件中,如自己開發的外掛程式。

 

$.Callbacks構造的對象(以callbacks樣本)主要包括以下方法:

  1. callbacks.add
  2. callbacks.remove
  3. callbacks.has
  4. callbacks.empty
  5. callbacks.disable
  6. callbacks.fire
  7. callbacks.fireWith
  8. callbacks.fired
  9. callbacks.lock
  10. callbacks.locked

 

1. callbacks.add 添加一個函數到回調隊列

function fn1() {console.log(1)}function fn2() {console.log(2)}var callbacks = $.Callbacks();// 方式1callbacks.add(fn1);// 方式2 一次添加多個回呼函數callbacks.add(fn1, fn2);// 方式3 傳數組callbacks.add([fn1, fn2]);// 方式4 函數和數組摻和callbacks.add(fn1, [fn2]);

傳數組進去實際在add內部判斷如果是數組會遞迴調用私人的add函數。此外,需注意add方法預設不去重,比如這裡fn1添加兩次,fire時會觸發兩次。私人add方法有趣,它使用了具名函數立即執行其名僅在函數內可用。中所圈之處

 

2. callbacks.remove 從回調隊列中刪除一個函數

function fn1() {    console.log(1)}function fn2() {    console.log(2)}var callbacks = $.Callbacks();callbacks.add(fn1, fn2);callbacks.remove(fn1);

此時fire只會觸發fn2了。

 

此外remove方法會把添加多次的函數如fn1,全部刪除掉。為此還和cmc和nick討論為啥remove內部不用if而用while(開始我以為是jQuery寫錯了)。如下

var callbacks = $.Callbacks();callbacks.add(fn1, fn2, fn1, fn2);callbacks.remove(fn1);

此時會把add兩次的fn1都刪掉,fire時只觸發fn2兩次。換成if則只刪fn1一次。

 

3. callbacks.has 判斷是否添加過某回呼函數,不想重複添加時很有用

function fn1() {    console.log(1)}var callbacks = $.Callbacks();callbacks.add(fn1);if (!callbacks.has(fn1)) {    callbacks.add(fn1);}

 

4. callbacks.empty 清空所有的回呼函數

function fn1() {console.log(1)}function fn2() {console.log(2)}var callbacks = $.Callbacks();callbacks.add(fn1);callbacks.add(fn2);callbacks.empty();

此時再fire不會觸發任何函數。empty函數實現很簡單,只是把內部的隊列管理對象list重設為一個空數組。這裡可以瞭解清空數組的幾種方式。

 

5. callbacks.disable 禁用該對象

function fn1() {    console.log(1)}function fn2() {    console.log(2)}var callbacks = $.Callbacks();callbacks.disable();callbacks.add(fn1); // 不起作用callbacks.add(fn2); // 不起作用callback.remove(fn1); // 不起作用callbacks.fire(); // 不起作用

調用後再使用add, remove, fire等方法均不起作用。該方法內不是實際是將隊列管理對象list、stack、memory都置undefined了。

 

6. callbacks.fire 主動觸發添加回呼函數

function fn() {    console.log(this); // 上下文是callbacks    console.log(arguments); // [3]}var callbacks = $.Callbacks();callbacks.add(fn);callback.fire(3);

前面已經提到了,fire方法用來觸發回呼函數,預設的上下文是callbacks對象,還可以傳參給回呼函數。

 

7. callbacks.fireWith 同fire,但可以指定執行內容

function fn() {    console.log(this); // 上下文是person    console.log(arguments); // [3]}var person = {name: 'jack'};var callbacks = $.Callbacks();callbacks.add(fn);callback.fireWith(person, 3);

其實fire內部調用的是fireWith,只是將上下文指定為this了,而this正是$.Callbacks構造的對象。

 

8. callbacks.fired 判斷是否有主動觸發過(調用fire或fireWith方法)

function fn1() {    console.log(1)}var callbacks = $.Callbacks();callbacks.add(fn1);callbacks.fired(); // falsecallbacks.fire();callbacks.fired(); // true

注意,只要調用過一次fire或fireWith就會返回true。

 

9. callbacks.lock 鎖定隊列的狀態

 

10. callbacks.locked 判斷是否鎖定狀態

 

 

$.Callbacks構造時可配置的參數Flags是可選的,字串類型以空格分隔,有如下

  1. once
  2. memory
  3. unique
  4. stopOnFalse

 

1. once 確保回呼函數僅執行一次

function fn() {    console.log(1)}var callbacks = $.Callbacks('once');callbacks.add(fn);callbacks.fire(); // 列印1callbacks.fire(); // fn不再觸發

 

2. memory 記憶callbacks

function fn1() {console.log(1)}function fn2() {console.log(2)}var callbacks = $.Callbacks('memory');callbacks.add(fn1);callbacks.fire(); // 必須先firecallbacks.add(fn2); // 此時會立即觸發fn2

memory有點繞,本意是記憶的意思。實際它的用法有點詭異,需結合特定情境來看(如jQuery.Deferred)。當首次調用fire後,之後每次add都會立即觸發。比如先callbacks.fire(),再callbacks.add(fn1),這時fn1會立即被調用。

 

如果是大量新增的,也都會被觸發

function fn1() {console.log(1)}function fn2() {console.log(2)}function fn3() {console.log(3)}var callbacks = $.Callbacks('memory');callbacks.add(fn1);callbacks.fire();callbacks.add([fn2, fn3]); // output 2, 3

 

3. unique 去除重複的回呼函數

function fn1() {console.log(1)}function fn2() {console.log(2)}var callbacks = $.Callbacks('unique');callbacks.add(fn1);callbacks.add([fn1, fn2]); // 再次添加fn1callbacks.fire(); // output 1, 2

這個很好理解,之前用has判斷去重,使用unique屬性則更方便。本例先add一次fn1,第二次再add時內部則會去重。因此最後fire時只輸出“1,2”而不是“1,1,2”。

 

4. stopOnFalse 回呼函數返回false時中斷回調隊列的迭代

function fn1() {console.log(1)}function fn2() {console.log(2)return false // 注意這裡}function fn3() {console.log(3)}var callbacks = $.Callbacks('stopOnFalse');callbacks.add(fn1, fn2, fn3);callbacks.fire(); // output 1,2

從該屬性名稱就能知了它的意圖,即回呼函數通過return false來停止後續的回調執行。該樣本添加了3個回調,fn2中使用return false,當fire執行到fn2時會停止執行,後續的fn3就不會被調用了。

 

用$.Callbacks實現觀察者模式

// 觀察者模式var observer = {hash: {},subscribe: function(id, callback) {if (typeof id !== 'string') {return}if (!this.hash[id]) {this.hash[id] = $.Callbacks()this.hash[id].add(callback)} else {this.hash[id].add(callback)}},publish: function(id) {if (!this.hash[id]) {return}this.hash[id].fire(id)}}// 訂閱observer.subscribe('mailArrived', function() {alert('來信了')})observer.subscribe('mailArrived', function() {alert('又來信了')})observer.subscribe('mailSend', function() {alert('發信成功')})// 發布setTimeout(function() {observer.publish('mailArrived')}, 5000)setTimeout(function() {observer.publish('mailSend')}, 10000)

  

 

註:閱讀版本為1.8.3

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.