1 (function( jQuery ) {
  2
  3 // String to Object flags format cache
  4 var flagsCache = {};
  5
  6 // Convert String-formatted flags into Object-formatted ones and store in cache
  7 // 将字符串形式的flags转换成对象形式,并且存到cache中,例: "once memory" =>  {"once":true,"memory":true}
  8 function createFlags( flags ) {
  9     var object = flagsCache[ flags ] = {},
 10         i, length;
 11     flags = flags.split( /\s+/ );
 12     for ( i = 0, length = flags.length; i < length; i++ ) {
 13         object[ flags[i] ] = true;
 14     }
 15     return object;
 16 }
 17
 18 /*
 19  * 用以下参数创建一个回调函数列表:
 20  *
 21  *    flags:    可选的以空格分隔的flags,会影响回调函数列表的行为
 22  *
 23  *
 24  * 默认情况下,回调函数列表的行为如同一个事件回调函数列表一样,并且可以触发多次。
 25  *
 26  * 可选的 flags:
 27  *
 28  *    once:            会确保回调列表只被触发一次(像Deferred一样), 这个不会阻止memory模式,也就是说 "once memory"的参数下 虽然只能fire一次,但是fire后再add 还是有效果的
 29  *
 30  *    memory:          会记录上一次fire的上下文(一般是$.callbacks自身)和参数,并且会立即以最近一次fire记录下的上下文和参数执行新添加进来回调函数 (像Deferred一样)
 31  *                     具体看 (1) 88行 memory = !flags.memory || [ context, args ];  保存memory模式下的 函数上下文和参数
 32  *                           (2) 127-130行 self.add添加回调函数时候的处理
 33  *
 34  *    unique:          会确同一个回调函数只在列表中出现一次
 35  *
 36  *    stopOnFalse:     其中一个回调函数返回false即停止调用其余函数
 37  *
 38  */
 39 jQuery.Callbacks = function( flags ) {
 40
 41     // Convert flags from String-formatted to Object-formatted
 42     // (we check in cache first)
 43     flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
 44
 45     var // 实际存放回调函数的容器
 46         list = [],
 47
 48         // 用以存放可重复fire(即非once模式),重复fire的回调函数  例: 在一个回调函数体里边也调用了fire的情景
 49         // 另外这个stack 还用以标示整个回调列表是否处于锁定状态(仅仅判可不可触发fire, 还是可以add, remove的)  205行 + 192-202行
 50         stack = [],
 51
 52         // 上次fire的上下文和参数,
 53         // 可能的值: (1) [context,args]
 54         //          (2) true , 非记忆执行上下文和参数 或者 stopOnFalse模式下有返回为false的回调函数
 55         memory,
 56         // 标识当前是否处于fire状态
 57         firing,
 58         // fire第一个执行的回调函数在list中的索引位置 (内部fireWith使用和add导致list个数变化时修正执行中的索引位置 128行)
 59         firingStart,
 60         // 循环的结尾位置 (如果在firing状态下self.add添加新函数和self.remove移除函数时候会调整 123行 146行 )
 61         firingLength,
 62         // 当前触发的函数索引 ,需要的时候会调整
 63         firingIndex,
 64         //工具方法: 添加一个或多个(args为数组时)函数到list
 65         add = function( args ) {
 66             var i,
 67                 length,
 68                 elem,
 69                 type,
 70                 actual;
 71             for ( i = 0, length = args.length; i < length; i++ ) {
 72                 elem = args[ i ];
 73                 type = jQuery.type( elem );
 74                 if ( type === "array" ) {
 75                     // 递归检查
 76                     add( elem );
 77                 } else if ( type === "function" ) {
 78                     // 非unique模式且新回调函数不存在
 79                     if ( !flags.unique || !self.has( elem ) ) {
 80                         list.push( elem );
 81                     }
 82                 }
 83             }
 84         },
 85         //工具方法: 触发回调函数
 86         fire = function( context, args ) {
 87             args = args || [];
 88             memory = !flags.memory || [ context, args ];
 89             firing = true;
 90             firingIndex = firingStart || 0;
 91             firingStart = 0;
 92             firingLength = list.length;
 93             for ( ; list && firingIndex < firingLength; firingIndex++ ) {
 94                  if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
 95                     memory = true; // 标记为终止  注意看106行, 销毁$.callbacks
 96                     break;
 97                 }
 98             }
 99             firing = false; // 标记执行结束
100             if ( list ) {
101                 if ( !flags.once ) { // fire完后检查是否有回调函数内部重复fire保留下来的执行上下文和参数
102                     if ( stack && stack.length ) {
103                         memory = stack.shift();
104                         self.fireWith( memory[ 0 ], memory[ 1 ] );
105                     }
106                 } else if ( memory === true ) { // stopOnFalse
107                     self.disable();
108                 } else {
109                     list = [];
110                 }
111             }
112         },
113         // 实际的回调函数对象
114         self = {
115             //实例方法: 添加一个或多个(args为数组时)函数到list
116             add: function() {
117                 if ( list ) {
118                     var length = list.length;
119                     add( arguments );
120                     // Do we need to add the callbacks to the
121                     // current firing batch?
122                     if ( firing ) {
123                         firingLength = list.length;
124                     // With memory, if we're not firing then
125                     // we should call right away, unless previous
126                     // firing was halted (stopOnFalse)
127                     } else if ( memory && memory !== true ) {
128                         firingStart = length;
129                         fire( memory[ 0 ], memory[ 1 ] );
130                     }
131                 }
132                 return this;
133             },
134             // 从列表中移除函数
135             remove: function() {
136                 if ( list ) {
137                     var args = arguments,
138                         argIndex = 0,
139                         argLength = args.length;
140                     for ( ; argIndex < argLength ; argIndex++ ) {
141                         for ( var i = 0; i < list.length; i++ ) {
142                             if ( args[ argIndex ] === list[ i ] ) {
143                                 // 在firing时移除函数,需要修正当前索引firingIndex和长度firingLength
144                                 if ( firing ) {
145                                     if ( i <= firingLength ) {
146                                         firingLength--;
147                                         if ( i <= firingIndex ) {
148                                             firingIndex--;
149                                         }
150                                     }
151                                 }
152                                 // Remove the element
153                                 list.splice( i--, 1 );
154                                 // 如果是unique模式(这时不会有重复的函数),移除一次就可以了
155                                 if ( flags.unique ) {
156                                     break;
157                                 }
158                             }
159                         }
160                     }
161                 }
162                 return this;
163             },
164             // 判断指定回调函数是否存在
165             has: function( fn ) {
166                 if ( list ) {
167                     var i = 0,
168                         length = list.length;
169                     for ( ; i < length; i++ ) {
170                         if ( fn === list[ i ] ) {
171                             return true;
172                         }
173                     }
174                 }
175                 return false;
176             },
177             // Remove all callbacks from the list
178             empty: function() {
179                 list = [];
180                 return this;
181             },
182             // Have the list do nothing anymore
183             disable: function() {
184                 list = stack = memory = undefined;
185                 return this;
186             },
187             // Is it disabled?
188             disabled: function() {
189                 return !list;
190             },
191             // Lock the list in its current state
192             lock: function() {
193                 stack = undefined;
194                 if ( !memory || memory === true ) {
195                     self.disable();
196                 }
197                 return this;
198             },
199             // Is it locked?
200             locked: function() {
201                 return !stack;
202             },
203             // Call all callbacks with the given context and arguments
204             fireWith: function( context, args ) {
205                 if ( stack ) { // stack=[] 也是true
206                     if ( firing ) {
207                         if ( !flags.once ) {
208                             stack.push( [ context, args ] );
209                         }
210                     } else if ( !( flags.once && memory ) ) {
211                         fire( context, args );
212                     }
213                 }
214                 return this;
215             },
216             // Call all the callbacks with the given arguments
217             fire: function() {
218                 self.fireWith( this, arguments );
219                 return this;
220             },
221             // To know if the callbacks have already been called at least once
222             fired: function() {
223                 return !!memory; // 其实这个有问题, 当调用disable() 的时候 memory==undefined
224             }
225         };
226
227     return self;
228 };
229
230 })( jQuery );

下面是一些检验这些参数逻辑的代码:

 1      /*
 2              jquery.Callbacks
 3          */
 4          // var testUrl="http://www.runoob.com/try/ajax/demo_test.php";
 5          // var callbacks=new jQuery.Callbacks("memory");
 6          // callbacks.add(function(){alert("first callback")});
 7          // callbacks.add(function(){alert("second callback")});
 8          // callbacks.fire();
 9          // memory
10         // callbacks.add(function(){alert("third callback")});
11
12
13         var callback2=
14          jQuery.Callbacks("once memory"), // once 表示回调函数列表只会fire一次,但是还会运行memory机制,也不限制回调函数列表里边有多个相同的函数(可以用unique 去重)
15          something = true;
16         function fn1(args)
17         {
18              alert('fn1 args:'+args);
19              console.log(this);
20             if(something){
21                 callback2.fire(" test:第2次触发");
22                 callback2.fire(" test:第3次触发"); //fire内部再触发的话 先放入stack中
23                 something=false;
24             }
25         }
26         function fn2(){
27             alert('fn2');
28         }
29         callback2.add(fn1);
30         callback2.add(fn2);
31
32         callback2.fire('测试:第1次触发');
33         callback2.fire('测试:第4次触发');  //once模式 只会fire一次, memory在add的时候促发
34         callback2.add(fn2);

View Code

源码地址

转载于:https://www.cnblogs.com/mushishi/p/5759307.html

jQuery.callbacks 注释相关推荐

  1. jQuery Callbacks

    jQuery.Callbacks是jQuery的多用途核心组件,专职负责回调函数列队管理,其在jQuery的$.ajax() 和 $.Deferred()提供了一些基础功能. 其主要提供了易于管理的批 ...

  2. jQuery.Callbacks之demo

    jQuery.Callbacks是jquery在1.7版本之后加入的,是从1.6版中的_Deferred对象中抽离的,主要用来进行函数队列的add.remove.fire.lock等操作,并提供onc ...

  3. jquery Callbacks 回调对象的读书笔记-源码分析

    2019独角兽企业重金招聘Python工程师标准>>> Callbacks:回调对象,函数的一个统一管理(观察者模式) 基本使用 function test1() {console. ...

  4. jquery框架封装及解析原理+自己搭建jquery框架+注释

    <script> //利用自执行函数封装jq代码,避免暴露太多的全局变量 (function (window) { //为了以后能方便借用数组的各种方法,提前存到变量中,全局都是用这一个数 ...

  5. jquery源码之低调的回调函数队列--Callbacks

    jQuery中有一个很实用的函数队列,可能我们很少用到,但他在jQuery内部却有着举足轻重的地位. 他就是Callbacks. jQuery作者用它构建了很多非常重要的模块.比如说$.Deferre ...

  6. jQuery Deffered Callbacks

    jQuery Deffered jQuery Callbacks 转载于:https://www.cnblogs.com/veryvalley/p/10298970.html

  7. jQuery源码分析 Callbacks

    jQuery版本 version = "1.11.1" 前言 $.Callbacks() 提供了一种强大的方法来管理回调函数队列,采用了观察者模式,通过add添加操作到队列当中,通 ...

  8. jquery源码分析(四)——回调对象 Callbacks

    借用百度百科来说明下回调函数: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该 ...

  9. jquery的回调对象Callbacks详解

    Callbacks : 对函数的统一管理 Callbacks的options参数接受4个属性,分别是 once : 只执行一次 momery : 记忆 stopOnFalse : 强制退出循环 uni ...

  10. jQuery源码逐行分析学习01(jQuery的框架结构简化)

    最近在学习jQuery源码,在此,特别做一个分享,把所涉及的内容都记录下来,其中有不妥之处还望大家指出,我会及时改正.望各位大神不吝赐教!同时,这也是我的第一篇前端技术博客,对博客编写还不是很熟悉,美 ...

最新文章

  1. python哪个版本好-python下载哪个版本好
  2. (23/24) webpack实战技巧:如何在webpack环境中使用Json
  3. save product in COMMPR01的调试和调用栈
  4. java 异常 最好在action捕获还是service_到底应该在action里面捕捉异常还是在service里面捕捉异常?...
  5. go的转义字符,字符串本身带有特殊符号
  6. 基于libpcan库can总线操作的Barrett 机械手控制及腕部六维力传感器驱动
  7. shell中单引号、双引号、反引号、反斜杠的使用
  8. 虚拟化系列-Citrix XenServer 6.1 网络管理
  9. ios 获取最后一个cell_ios – UICollectionView estimatedItemSize – 最后一个单元格未对齐...
  10. 机器学习十大算法都是何方神圣?看完你就懂了
  11. pcd格式点云的显示程序
  12. Few-Shot Object Detection with Attention-RPN and Multi-Relation Detector 论文翻译
  13. 计算机注销的快捷键,电脑死机了按哪个键注销电脑
  14. 三国演义主要人物个人经历
  15. 数学笔记10——拉格朗日中值定理
  16. 如何微信公众号中的视频保存下来
  17. angularJS1 异常Error: [$injector:unpr]
  18. 岁月温柔-9 妈妈吃人参果的后遗症
  19. “双 亲 委 派 机 制”
  20. 数据库:数据的独立性

热门文章

  1. 基于WebActivator的改进版本KudyStudio.Web.Activating讲解与下载
  2. EditPlus中有用的快捷键
  3. Visual Studio里的BUG??
  4. MoneyRunner API汇总
  5. Sitecore开发 IP地理定位服务入门
  6. Azure上七层负载均衡APP Gateway
  7. Android Activity launchMode研究
  8. SharpZipLib解压缩时中文名乱码[解决]
  9. 在Linux Redhat 9.0使用YUM
  10. 20190905 Lombok常用注解