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 实现创建文件夹和创建日志文件
一.实现创建文件夹和日志 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author: nulige import os import datetime ...
- hdata datax交流总结
http://blog.csdn.net/zlm838687/article/details/74781522 hdata datax交流总结 今天和阿里云的同学就数据同步做了简要的交流,下面就交流的 ...
- 【原创】SpringBoot & SpringCloud 快速入门学习笔记(完整示例)
[原创]SpringBoot & SpringCloud 快速入门学习笔记(完整示例) 1月前在系统的学习SpringBoot和SpringCloud,同时整理了快速入门示例,方便能针对每个知 ...
- Codeforces #263 div2 解题报告
比赛链接:http://codeforces.com/contest/462 这次比赛的时候,刚刚注冊的时候非常想好好的做一下,可是网上喝了个小酒之后.也就迷迷糊糊地看了题目,做了几题.一觉醒来发现r ...
- python——定时闹钟讲解
自己写的闹钟, 只可以播放wav格式的音频. import time import sys soundFile = 'sound.wav' not_executed = 1 def soundStar ...
- (七)Thymeleaf的 th:* 属性之—— th: ->设值& 遍历迭代& 条件判断
3.4 属性值的设置 3.4.1 使用th:attr来设置属性的值 <form action="subscribe.html" th:attr="action=@{ ...
- 解决zabbix“ZBX_NOTSUPPORTED: Timeout while executing a shell script”报错
如题所示,在zabbix_server使用zabbix_get获取自定义“UserParameter”对应的脚本的数据时,出现了如题所示的报错信息 [root@nmp01 scripts]# /usr ...
- Android下的Handler
coder是没必要重复造轮子的,写博客亦如此.因为工作忙,学的东西比较多,没法自己来写博客.自己想了个思路就是,把别人的技术精华拿过来,从简到难,慢慢学习.最后提炼,得到自己想学的东西即可,等有时间了 ...
- Laravel5.4使用Memcached缓存
修改默认的缓存驱动 Laravel默认的缓存驱动是file,想要切换为Memcached需要修改.env文件.把CACHE_DRIVER=file改为CACHE_DRIVER=memcached,改好 ...
- Trie|如何用字典树实现搜索引擎的关键词提示功能
Trie字典树 Trie字典树又称前缀树,顾名思义,是查询前缀匹配的一种树形数据结构 可以分为插入(创建) 和 查询两部分.参考地址极客时间 下图为插入字符串的过程: 创建完成后,每个字符串最后一个字 ...