整個(gè)$.Callbacks的源碼很少,它是一個(gè)工廠函數(shù),使用函數(shù)調(diào)用(非new,它不是一個(gè)類)創(chuàng)建對(duì)象,它有一個(gè)可選參數(shù)flags用來(lái)設(shè)置回調(diào)函數(shù)的行為,對(duì)外的接口也就是self的返回。
jQuery.Callbacks()的API列表如下:
callbacks.add() :回調(diào)列表中添加一個(gè)回調(diào)或回調(diào)的集合。 callbacks.disable() :禁用回調(diào)列表中的回調(diào)。 callbacks.disabled() :確定回調(diào)列表是否已被禁用。 callbacks.empty() :從列表中刪除所有的回調(diào)。 callbacks.fire() :用給定的參數(shù)調(diào)用所有的回調(diào)。 callbacks.fired() :訪問(wèn)給定的上下文和參數(shù)列表中的所有回調(diào)。 callbacks.fireWith() :訪問(wèn)給定的上下文和參數(shù)列表中的所有回調(diào)。 callbacks.has() :確定列表中是否提供一個(gè)回調(diào)。 callbacks.lock() :鎖定當(dāng)前狀態(tài)的回調(diào)列表。 callbacks.locked() :確定回調(diào)列表是否已被鎖定。 callbacks.remove() :從回調(diào)列表中的刪除一個(gè)回調(diào)或回調(diào)集合。
源碼結(jié)構(gòu):
jQuery.Callbacks = function(options) { options = typeof options === "string" ? (optionsCache[options] || createOptions(options)) : jQuery.extend({}, options); //實(shí)現(xiàn)代碼 fire = function() {} self = { add: function() {}, remove: function() {}, has: function(fn) {}, empty: function() {}, disable: function() {}, disabled: function() {}, lock: function() {}, locked: function() {}, fireWith: function(context, args) {}, fire: function() {}, fired: function() {} }; return self; };
整個(gè)結(jié)構(gòu)要分三部分:
? Options參數(shù)緩存
? 內(nèi)部fire觸發(fā)器的設(shè)計(jì)
? 外部
參數(shù)的緩存設(shè)計(jì)
Callbacks是可以是接受的字符串的組合傳參數(shù),可以使用空格分割,代碼如下:
var opts = 'unique memory'; var object = {} jQuery.each(opts.match(/\S+/g) || [], function(_, flag) { object[flag] = true; });
這樣的操作其實(shí)是不需要重復(fù)的,所以我們可以設(shè)計(jì)一個(gè)緩存池,用來(lái)儲(chǔ)存重復(fù)的操作:
var optionsCache = {}; function createOptions(options) { var object = optionsCache[options] = {}; jQuery.each(options.match(rnotwhite) || [], function(_, flag) { object[flag] = true; }); return object; }
所以我們傳遞參數(shù)的時(shí)候,如果參數(shù)是字符串,我們可以直接從optionsCache緩存中去查找:
options = typeof options === "string" ? ( optionsCache[ options ] || createOptions( options ) ) : jQuery.extend( {}, options );
接口的設(shè)計(jì):
通過(guò)學(xué)習(xí)了觀察者模式的思路,我們知道callback需要在內(nèi)部維護(hù)著一個(gè)list的隊(duì)列數(shù)組,用于保存訂閱的對(duì)象數(shù)據(jù)。同時(shí)也需要提供了add、remove、fire等訂閱、發(fā)布、刪除類似的接口。
那么我們代碼是不是很簡(jiǎn)單是就是把訂閱對(duì)象給push給內(nèi)部list列表?
實(shí)現(xiàn)思路就是: 構(gòu)建一個(gè)存放回調(diào)的數(shù)組,如var list = []
,通過(guò)閉包使這條回調(diào)數(shù)組保持存在。添加回調(diào)時(shí),將回調(diào)push進(jìn)list,執(zhí)行則遍歷list執(zhí)行回調(diào)。
后面幾節(jié)我們會(huì)通過(guò)簡(jiǎn)單的模擬實(shí)現(xiàn)去剖析設(shè)計(jì)的思路。
請(qǐng)驗(yàn)證,完成請(qǐng)求
由于請(qǐng)求次數(shù)過(guò)多,請(qǐng)先驗(yàn)證,完成再次請(qǐng)求
打開(kāi)微信掃碼自動(dòng)綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報(bào)