Callback模組是用來管理回呼函數,也作為deferred延遲物件得基礎部分,現在一起來看看他的原始碼。
可選參數:
Options: once: 是否最多执行一次, memory: 是否记住最近的上下文和参数 stopOnFalse: 当某个回调函数返回false时中断执行 unique: 相同得回调只被添加一次
這是可選參數,下面可以進行試驗:
var a = function (value) { console.log('a:' + value); }; var b = function (value) { console.log('b:' + value); }; var callbacks = $.Callbacks(); callbacks.add(a); callbacks.fire(['hello']); callbacks.add(b); callbacks.fire('中');
下面是他的輸出結果:
a: hello, a:中, b:中
可以看到得是,當我們第二次fire得時候,a函數也會執行。
在加入參數進行實驗,首先加入memory
var callbacks = $.Callbacks({ memory: true }); callbacks.add(a); callbacks.fire('hello'); callbacks.add(b); 输出: a:hello, b:hello
加入memory參數,memory記錄上一次觸發回呼函數,之後新增的函數都用這參數立即執行。在來看once的使用
var callbacks = $.Callbacks({ once: true }); callbacks.add(a); callbacks.fire('hello'); callbacks.fire('中'); 输出: a:hello
可以看到的是,雖然執行了兩次fire方法,但只輸出了一次結果。其他兩個參數很好理解,細節的部分自己去嘗試。
$.Callbacks = function(options) { options = $.extend({}, options) var memory, fired, firing, firingStart, firingLength, firingIndex, list = [], stack = !options.once && [] }
再看看各個參數的意義,memory會在記憶模式下記住上一次觸發的上下文和參數,fired代表回調是否已經觸發過,firing表示回調正在觸發,firingStart回呼任務開始的位置,firingLength回呼任務的長度,firingIndex目前回呼的索引,list表示真實的回呼佇列,在不是觸發一次的情況下,用來快取觸發過程中沒有執行的任務參數。
fire = function(data) { memory = options.memory && data fired = true firingIndex = firingStart || 0 firingStart = 0 firingLength = list.length firing = true for ( ; list && firingIndex < firingLength ; ++firingIndex ) { if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) { memory = false break } } firing = false if (list) { if (stack) stack.length && fire(stack.shift()) else if (memory) list.length = 0 else Callbacks.disable() } }
fire函數是唯一內建的函數,他的作用是用來觸發list的回呼執行,首先看看他傳入的參數,和咱們在外部呼叫$.Callbacks的fire還不太一樣,這裡的data是一個數組,data[0]表示上下文,data[1]是方法呼叫的參數。然後就是各個參數的初始化,memory表示如果options.memory為true,則保存data,fired為true,如果firingStart為0,那麼firingIndex 為0,firingStart置為0,正在觸發的回調標記firing為true。
接著遍歷回呼列表,逐一執行回呼,這個裡邊的if判斷表示的是如果回呼函數回傳的是false並且options.stopOnFalse是false,則清空memory的快取。遍歷完成後,將執行的狀態改為false。如果list存在,stack也存在,把任務參數取出來,呼叫fire函數執行。如果memory存在,則清空列表,否則進行回調執行
最終這個檔案回傳的是Callbacks,我們來看看他的具體實作:
Callbacks = { add: function () { if (list) { var start = list.length, add = function (args) { $.each(args, funciton(_, arg) { if (typeof arg === 'function') { if (!options.unique || !Callbacks.has(arg)) list.push(arg); } else if (arg && arg.length && typeof arg !== 'string') add(arg); }) } add(arguments) if (firing) firingLength = list.length; else if (memory) { firingStart = start; fire(memory) } } return this; } }
這個函數主要的作用就是像list裡邊push回調。首先判斷list是否存在,如果存在,start賦值為list的長度,在內部加入一個add方法,內部add方法主要是在list中加入回調,如果我們傳入的參數是數組,就再次呼叫add方法。然後就是呼叫add方法,把arguments傳進去。如果回呼正在進行,則修正回呼任務的長度firingLength為目前任務清單的長度,以便後續新增的回呼函數可以執行。如果memory存在,則把開始設定為新新增清單的第一位,然後呼叫fire。
我們再來看看fireWith的做法:
fireWith: function(context, args) { if (list && (!fired || stack)) { args = args || []; args = [context, args.slice ? args.slice() : args]; if (firing) stack.push(args); else fire(args); } return this; }
傳入的參數包含上下文,和參數清單。函數執行的條件是list存在且回呼沒有執行或stack存在,stack可以為空。首先對args進行重新賦值,args[0]是上下文,args[1]是複製過來的列表。如果回調正在進行,請向stack裡邊添加args,或者就執行args。
相關文章:
#以上是【Javascript】zepto源碼Callback分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!