多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > web前端 > jquery > jQuery1.8.2源碼解析之jQuery.Callbacks

jQuery1.8.2源碼解析之jQuery.Callbacks

來源:程序員人生   發布時間:2014-03-30 07:09:06 閱讀次數:3030次

jQuery1.8.2源碼解析之jQuery.Callbacks,已經在代碼中添加了詳細的注釋,有需要的朋友看下邊的代碼就可以了。這樣在使用時就方便了許多。

代碼:

// String to Object options format cache
// 是對option的一個緩存,避免每次都要createOptions
// 每一個option類似這樣
// {
// memory : true
// ,once : true
// ,...
// }
var optionsCache = {};

// Convert String-formatted options into Object-formatted ones and store in cache
function createOptions( options ) {
var object = optionsCache[ options ] = {};
jQuery.each( options.split( core_rspace ), function( _, flag ) {
object[ flag ] = true;
});
return object;
}

/*
* Create a callback list using the following parameters:
*
* options: an optional list of space-separated options that will change how
* the callback list behaves or a more traditional option object
*
* By default a callback list will act like an event callback list and can be
* "fired" multiple times.
*
* Possible options:
*
* once: will ensure the callback list can only be fired once (like a Deferred)
*
* memory: will keep track of previous values and will call any callback added
* after the list has been fired right away with the latest "memorized"
* values (like a Deferred)
*
* unique: will ensure a callback can only be added once (no duplicate in the list)
*
* stopOnFalse: interrupt callings when a callback returns false
*
*/
jQuery.Callbacks = function( options ) {

// Convert options from String-formatted to Object-formatted if needed
// (we check in cache first)
// options也可以是一個對象
options = typeof options === "string" ?
( optionsCache[ options ] || createOptions( options ) ) :
jQuery.extend( {}, options );

var // Last fire value (for non-forgettable lists)
memory,
// Flag to know if list was already fired
fired,
// Flag to know if list is currently firing
firing,
// First callback to fire (used internally by add and fireWith)
firingStart,
// End of the loop when firing
firingLength,
// Index of currently firing callback (modified by remove if needed)
firingIndex,
// Actual callback list
list = [],
// Stack of fire calls for repeatable lists
// 只有在沒有設置了once時,stack才存在
// stack用來存儲參數信息(此時函數列表已經處于firing狀態,必須將其他地方調用fire時的參數存儲,之后再至此執行fire
stack = !options.once && [],
// Fire callbacks
fire = function( data ) {
// 如果設置memory,那么每一次fire的數據將會被保存在memory中,作為下次調用add時參數
memory = options.memory && data;
fired = true;
firingIndex = firingStart || 0;
// 重置fireStarting為0,因為add操作(memory)可能改變它
firingStart = 0;
firingLength = list.length;
firing = true;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
// 如果設置了stopOnFalse參數,那么當函數列表中有某個函數返回false時,停止后面函數的執行,并且取消memory(如果設置了)
if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
memory = false; // To prevent further calls using add
break;
}
}
firing = false;
if ( list ) {
// 如果stack存在,那么將之前存儲的第一個參數取出,繼續fire,直到stack為空
if ( stack ) {
if ( stack.length ) {
fire( stack.shift() );
}
// 如果stack不存在(即設置了once)
// 那么如果設置了memory,那么將之前函數列表清空,也就是說memory還在,add操作可以處罰函數立即執行
} else if ( memory ) {
list = [];
} else {
self.disable();
}
}
},
// Actual Callbacks object
// 實際返回的Callbacks對象
self = {
// Add a callback or a collection of callbacks to the list
// 添加函數或者函數集(數組或者偽數組)到函數列表中去
add: function() {
if ( list ) {
// First, we save the current length
var start = list.length;
(function add( args ) {
jQuery.each( args, function( _, arg ) {
var type = jQuery.type( arg );
// 如果arg是函數
// 如果設置unique,則在list中查找是否函數已存在,若存在忽略掉,否則push進list
// 如果沒有設置unique,則直接push進list
if ( type === "function" && ( !options.unique || !self.has( arg ) ) ) {
list.push( arg );

// 如果arg是數組或者偽數組,則遞推push進list
} else if ( arg && arg.length && type !== "string" ) {
// Inspect recursively
// 遞歸(成員為函數集)
add( arg );
}
});
})( arguments );
// Do we need to add the callbacks to the
// current firing batch?
// 在添加函數(集)時

// 如果函數列表正在依次執行回調函數(即firing狀態),在某一個callback中執行add(fn)操作
// 那么立即修改fireLength以便fire時函數列表能夠執行到剛添加的函數(集)
if ( firing ) {
firingLength = list.length;
// With memory, if we're not firing then
// we should call right away
// 如果不是firing狀態,并且設置了memory(肯定是在fired狀態時才會執行這一步,因為memory是在fire一次后才會被負值)
// 此時memory已經是上次fire是傳遞的參數,那么將會直接執行剛添加的函數集,而無需fire
} else if ( memory ) {
firingStart = start;
fire( memory );
}
}
return this;
},
// Remove a callback from the list
// 從函數列表中刪除函數(集)
remove: function() {
if ( list ) {
jQuery.each( arguments, function( _, arg ) {
var index;
// while循環的意義在于借助于強大的jQuery.inArray刪除函數列表中相同的函數引用(沒有設置unique的情況)
// jQuery.inArray將每次返回查找到的元素的index作為自己的第三個參數繼續進行查找,直到函數列表的盡頭
// splice刪除數組元素,修改數組的結構
while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
list.splice( index, 1 );
// Handle firing indexes
// 在函數列表處于firing狀態時,最主要的就是維護firingLength和firgingIndex這兩個值
// 保證fire時函數列表中的函數能夠被正確執行(fire中的for循環需要這兩個值)
if ( firing ) {
if ( index <= firingLength ) {
firingLength--;
}
if ( index <= firingIndex ) {
firingIndex--;
}
}
}
});
}
return this;
},
// Control if a given callback is in the list
// 判斷函數列表只能夠是否包含給定的fn
has: function( fn ) {
return jQuery.inArray( fn, list ) > -1;
},
// Remove all callbacks from the list
// 清空函數列表
empty: function() {
list = [];
return this;
},
// Have the list do nothing anymore
// 使函數列表作廢(不能再做任何事情)
disable: function() {
list = stack = memory = undefined;
return this;
},
// Is it disabled?
// 判斷是否函數列表是否disabled
disabled: function() {
return !list;
},
// Lock the list in its current state
lock: function() {
stack = undefined;
if ( !memory ) {
self.disable();
}
return this;
},
// Is it locked?
locked: function() {
return !stack;
},
// Call all callbacks with the given context and arguments
// 和fire相似,不相同的是fireWith可以給定上下文參數
// fire中就是調用fireWith中的context就是this(函數列表對象self)
fireWith: function( context, args ) {
args = args || [];
args = [ context, args.slice ? args.slice() : args ];
// 首先至少fire一次
// 如果執行過一次了(fired),那么若stack存在(即沒有設置once),將上下文環境和參數存儲,否則什么都不做
if ( list && ( !fired || stack ) ) {
if ( firing ) {
stack.push( args );
} else {
fire( args );
}
}
return this;
},
// Call all the callbacks with the given arguments
// 依次執行函數列表中的函數
fire: function() {
self.fireWith( this, arguments );
return this;
},
// To know if the callbacks have already been called at least once
// 判斷是否函數列表fire過(哪怕只有一次)
fired: function() {
return !!fired;
}
};

return self;
};
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
為碼而活
積分:4237
15粉絲
7關注
欄目熱點
關閉
程序員人生
主站蜘蛛池模板: 国产深夜福利在线观看网站 | 欧美亚洲综合网 | 久99久爱精品免费观看视频 | 爽爽视频在线观看 | 操操操网 | 国产天堂网 | 视频一二三区 | 可以在线观看的黄色网址 | 最近中文字幕2019免费版日本 | 免费看一区二区三区 | 国产日产欧美精品 | 亚洲另类精品xxxx人妖 | 日本一区精品久久久久影院 | 精品热线九九精品视频 | α毛片 | 综合图片区 | 国产未成女年一区二区 | 91四虎国自产在线播放线 | 国产成人看片免费视频观看 | 亚洲另类春色小说 | 成人精品久久 | 国产91精品久久久久久久 | 性色生活免费看性大片 | 国产精品自拍在线 | 日本中文字幕网 | 欧美丝袜高跟鞋一区二区 | 国产精品外围在线观看 | 亚洲看片网 | 国产福利免费看 | 最近高清中文在线观看国语字幕7 | 欧洲性大片xxxxx久久久 | 亚洲播播 | 天天拍久久 | 一二三四视频社区5在线高清视频 | 欧美一级高清片免费一级 | 亚洲精品老司机 | 精品精品国产高清a毛片 | 欧美一区=区三区 | 亚洲欧洲一区二区三区久久 | 一级a毛片免费观看久久精品 | 精品久久久久久中文字幕一区 |