jQuery.callbacks 注释
(function( jQuery ) { // String to Object flags format cache
var flagsCache = {}; // Convert String-formatted flags into Object-formatted ones and store in cache
// 将字符串形式的flags转换成对象形式,并且存到cache中,例: "once memory" => {"once":true,"memory":true}
function createFlags( flags ) {
var object = flagsCache[ flags ] = {},
i, length;
flags = flags.split( /\s+/ );
for ( i = , length = flags.length; i < length; i++ ) {
object[ flags[i] ] = true;
}
return object;
} /*
* 用以下参数创建一个回调函数列表:
*
* flags: 可选的以空格分隔的flags,会影响回调函数列表的行为
*
*
* 默认情况下,回调函数列表的行为如同一个事件回调函数列表一样,并且可以触发多次。
*
* 可选的 flags:
*
* once: 会确保回调列表只被触发一次(像Deferred一样), 这个不会阻止memory模式,也就是说 "once memory"的参数下 虽然只能fire一次,但是fire后再add 还是有效果的
*
* memory: 会记录上一次fire的上下文(一般是$.callbacks自身)和参数,并且会立即以最近一次fire记录下的上下文和参数执行新添加进来回调函数 (像Deferred一样)
* 具体看 (1) 88行 memory = !flags.memory || [ context, args ]; 保存memory模式下的 函数上下文和参数
* (2) 127-130行 self.add添加回调函数时候的处理
*
* unique: 会确同一个回调函数只在列表中出现一次
*
* stopOnFalse: 其中一个回调函数返回false即停止调用其余函数
*
*/
jQuery.Callbacks = function( flags ) { // Convert flags from String-formatted to Object-formatted
// (we check in cache first)
flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; var // 实际存放回调函数的容器
list = [], // 用以存放可重复fire(即非once模式),重复fire的回调函数 例: 在一个回调函数体里边也调用了fire的情景
// 另外这个stack 还用以标示整个回调列表是否处于锁定状态(仅仅判可不可触发fire, 还是可以add, remove的) 205行 + 192-202行
stack = [], // 上次fire的上下文和参数,
// 可能的值: (1) [context,args]
// (2) true , 非记忆执行上下文和参数 或者 stopOnFalse模式下有返回为false的回调函数
memory,
// 标识当前是否处于fire状态
firing,
// fire第一个执行的回调函数在list中的索引位置 (内部fireWith使用和add导致list个数变化时修正执行中的索引位置 128行)
firingStart,
// 循环的结尾位置 (如果在firing状态下self.add添加新函数和self.remove移除函数时候会调整 123行 146行 )
firingLength,
// 当前触发的函数索引 ,需要的时候会调整
firingIndex,
//工具方法: 添加一个或多个(args为数组时)函数到list
add = function( args ) {
var i,
length,
elem,
type,
actual;
for ( i = , length = args.length; i < length; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
// 递归检查
add( elem );
} else if ( type === "function" ) {
// 非unique模式且新回调函数不存在
if ( !flags.unique || !self.has( elem ) ) {
list.push( elem );
}
}
}
},
//工具方法: 触发回调函数
fire = function( context, args ) {
args = args || [];
memory = !flags.memory || [ context, args ];
firing = true;
firingIndex = firingStart || ;
firingStart = ;
firingLength = list.length;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
memory = true; // 标记为终止 注意看106行, 销毁$.callbacks
break;
}
}
firing = false; // 标记执行结束
if ( list ) {
if ( !flags.once ) { // fire完后检查是否有回调函数内部重复fire保留下来的执行上下文和参数
if ( stack && stack.length ) {
memory = stack.shift();
self.fireWith( memory[ ], memory[ ] );
}
} else if ( memory === true ) { // stopOnFalse
self.disable();
} else {
list = [];
}
}
},
// 实际的回调函数对象
self = {
//实例方法: 添加一个或多个(args为数组时)函数到list
add: function() {
if ( list ) {
var length = list.length;
add( arguments );
// Do we need to add the callbacks to the
// current firing batch?
if ( firing ) {
firingLength = list.length;
// With memory, if we're not firing then
// we should call right away, unless previous
// firing was halted (stopOnFalse)
} else if ( memory && memory !== true ) {
firingStart = length;
fire( memory[ ], memory[ ] );
}
}
return this;
},
// 从列表中移除函数
remove: function() {
if ( list ) {
var args = arguments,
argIndex = ,
argLength = args.length;
for ( ; argIndex < argLength ; argIndex++ ) {
for ( var i = ; i < list.length; i++ ) {
if ( args[ argIndex ] === list[ i ] ) {
// 在firing时移除函数,需要修正当前索引firingIndex和长度firingLength
if ( firing ) {
if ( i <= firingLength ) {
firingLength--;
if ( i <= firingIndex ) {
firingIndex--;
}
}
}
// Remove the element
list.splice( i--, );
// 如果是unique模式(这时不会有重复的函数),移除一次就可以了
if ( flags.unique ) {
break;
}
}
}
}
}
return this;
},
// 判断指定回调函数是否存在
has: function( fn ) {
if ( list ) {
var i = ,
length = list.length;
for ( ; i < length; i++ ) {
if ( fn === list[ i ] ) {
return true;
}
}
}
return false;
},
// 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: function() {
return !list;
},
// Lock the list in its current state
lock: function() {
stack = undefined;
if ( !memory || memory === true ) {
self.disable();
}
return this;
},
// Is it locked?
locked: function() {
return !stack;
},
// Call all callbacks with the given context and arguments
fireWith: function( context, args ) {
if ( stack ) { // stack=[] 也是true
if ( firing ) {
if ( !flags.once ) {
stack.push( [ context, args ] );
}
} else if ( !( flags.once && memory ) ) {
fire( context, 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
fired: function() {
return !!memory; // 其实这个有问题, 当调用disable() 的时候 memory==undefined
}
}; return self;
}; })( jQuery );
下面是一些检验这些参数逻辑的代码:
/*
jquery.Callbacks
*/
// var testUrl="http://www.runoob.com/try/ajax/demo_test.php";
// var callbacks=new jQuery.Callbacks("memory");
// callbacks.add(function(){alert("first callback")});
// callbacks.add(function(){alert("second callback")});
// callbacks.fire();
// memory
// callbacks.add(function(){alert("third callback")}); var callback2=
jQuery.Callbacks("once memory"), // once 表示回调函数列表只会fire一次,但是还会运行memory机制,也不限制回调函数列表里边有多个相同的函数(可以用unique 去重)
something = true;
function fn1(args)
{
alert('fn1 args:'+args);
console.log(this);
if(something){
callback2.fire(" test:第2次触发");
callback2.fire(" test:第3次触发"); //fire内部再触发的话 先放入stack中
something=false;
}
}
function fn2(){
alert('fn2');
}
callback2.add(fn1);
callback2.add(fn2); callback2.fire('测试:第1次触发');
callback2.fire('测试:第4次触发'); //once模式 只会fire一次, memory在add的时候促发
callback2.add(fn2);
jQuery.callbacks 注释的更多相关文章
- jQuery.Callbacks之demo
jQuery.Callbacks是jquery在1.7版本之后加入的,是从1.6版中的_Deferred对象中抽离的,主要用来进行函数队列的add.remove.fire.lock等操作,并提供onc ...
- jQuery回调、递延对象总结(上篇)—— jQuery.Callbacks
前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...
- jQuery.Callbacks 源码解读二
一.参数标记 /* * once: 确保回调列表仅只fire一次 * unique: 在执行add操作中,确保回调列表中不存在重复的回调 * stopOnFalse: 当执行回调返回值为false,则 ...
- jQuery源代码学习之四——jQuery.callbacks
自己实现的callbacks模块相较于jquery源代码中的callbacks模块有所简化,表面上看没有考虑firing这个参数,没有对之进行任何处理,即没有考虑在函数执行过程中,再次调用add,re ...
- jQuery.Callbacks之源码解读
在上一篇jQuery.Callbacks之demo主要说了Callbacks对象初始化常见的选项,这一篇主要分析下Callbacks对象的源代码,对给出两个较为繁琐的demo // String to ...
- jQuery回调、递延对象总结(一)jQuery.Callbacks详解
前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...
- jQuery: Callbacks
jQuery 中提供了一个Callback的工具类Callbacks,它提供了一个Callback Chain.使用它可以在一个chain上来执行相关操作.它也是jQuery中的ajax, Defer ...
- jquery.Callbacks的实现
前言 本人是一个热爱前端的菜鸟,一直喜欢学习js原生,对于jq这种js库,比较喜欢理解他的实现,虽然自己能力有限,水平很低,但是勉勉强强也算是能够懂一点吧,对于jq源码解读系列,博客园里有很多,推荐大 ...
- jQuery 2.0.3 源码分析 回调对象 - Callbacks
源码API:http://api.jquery.com/jQuery.Callbacks/ jQuery.Callbacks()是在版本1.7中新加入的.它是一个多用途的回调函数列表对象,提供了一种强 ...
随机推荐
- Python中将打印输出日志文件
一. 利用sys.stdout将print行导向到你定义的日志文件中,例如: import sys # make a copy of original stdout route stdout_back ...
- rpc接口mock平台
转载:http://blog.csdn.net/ronghuanye/article/details/71124320 1.简介 平台采用struts.spring.mybatis框架开发设计,主要用 ...
- m 调用传参图片切换
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- ionic准备之angular基础———服务provider 和 factory和service(9)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C#操作消息列队
首先安装消息队列MSMQ,在“计算机管理-服务和应用程序-消息队列-专用队列”中新建列队名称Demo: static void SendAndReceiveMsg() { MessageQueue m ...
- HTML to PDF pechkin
1. Goto Nuget 下载 Pechkin 控件 2. 创建需要打印的的PDF controller 和 Action, 这里会调用其他页面的内容进行打印. public ActionResul ...
- C# readonly和const的不同以及它的具体用法
在C#中,我们用const来定义常量.常量就是我定义一个变量,这个变量的值在整个软件的生命周期都不变.比如我想求一个圆形的面积,我就可以把π定义成一个常量,因为我事先知道圆周率是就是3.1415926 ...
- java中不能用小数点(.)来做分隔符
split()括号里是一个String的参数,所以一定要符合这种:split(".")形式,即点'.'要用双引号""括起来"."在java中 ...
- 用HTML5canvas绘制一个圆环形的进度表示
先看一下画出来的效果,如下图,这样一个圆环形的进度. 我这里使用HTML5的Canvas来要制作这样一个圆环形的进度, 首先是HTML页面,HTML5的文档标识是: 这个文档标识要比HTML4的简单 ...
- MVC进阶学习--View和Controller之间的数据传递(二)
1. 使用Request.Form MVC 将页面简单化,与WebForm中的事件机制完全不同,就和普通的html标签表单提交没有任何区别(当然WebForm中的事件机制其实也是表单提交).在表单提交 ...