博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jQuery.callbacks 注释
阅读量:5094 次
发布时间:2019-06-13

本文共 10290 字,大约阅读时间需要 34 分钟。

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 ) { // stopOnFalse107                     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 the121                     // current firing batch?122                     if ( firing ) {123                         firingLength = list.length;124                     // With memory, if we're not firing then125                     // we should call right away, unless previous126                     // 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和长度firingLength144                                 if ( firing ) {145                                     if ( i <= firingLength ) {146                                         firingLength--;147                                         if ( i <= firingIndex ) {148                                             firingIndex--;149                                         }150                                     }151                                 }152                                 // Remove the element153                                 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 list178             empty: function() {179                 list = [];180                 return this;181             },182             // Have the list do nothing anymore183             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 state192             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 arguments204             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 arguments217 fire: function() {218 self.fireWith( this, arguments );219 return this;220 },221 // To know if the callbacks have already been called at least once222 fired: function() {223 return !!memory; // 其实这个有问题, 当调用disable() 的时候 memory==undefined224 }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          // memory10         // 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

你可能感兴趣的文章
数据库连接字符串大全 (转载)
查看>>
java类加载和对象初始化
查看>>
对于负载均衡的理解
查看>>
django简介
查看>>
window.event在IE和Firefox的异同
查看>>
常见的js算法面试题收集,es6实现
查看>>
IO流写出到本地 D盘demoIO.txt 文本中
查看>>
(转)linux sort,uniq,cut,wc命令详解
查看>>
关于ExecuteNonQuery执行的返回值(SQL语句、存储过程)
查看>>
UVa540 Team Queue(队列queue)
查看>>
Screening technology proved cost effective deal
查看>>
【POJ2699】The Maximum Number of Strong Kings(网络流)
查看>>
spring boot配置跨域
查看>>
BZOJ 1996 合唱队(DP)
查看>>
进击吧!阶乘——大数乘法
查看>>
安卓学习资料推荐-25
查看>>
Mysql数据库备份和还原常用的命令
查看>>
关于退出当前页面在火狐的一些问题
查看>>
【项目实施】项目考核标准
查看>>
spring-aop AnnotationAwareAspectJAutoProxyCreator类
查看>>