JQuery中的回调对象
来源:互联网 发布:黑客技术入门教程软件 编辑:程序博客网 时间:2024/06/05 15:59
JQuery中的回调对象
回调对象(Callbacks object)模块是JQuery中的一个很基础的模块,很多其他的模块(比如Deferred、Ajax等)都依赖于Callbacks模块的实现。
本文主要描述回调对象的基本功能、具体实现,以及使用到的设计思想。
1. 基本功能
从jquery的API 中可以了解到,Callbacks对象是JQuery自1.7以后提供的一个管理回调函数的工具,提供基本的增加、删除、调用和禁用回调函数的能力。
1.1 基本配置
Callbacks提供如下四个配置供开发者使用:
- once 保证所有回调函数只能执行一次。
- memory 记录上一次调用回调函数的参数值。如果在调用回调函数之后又通过add新回调函数,那么会立即使用memory记录的值调用新增的回调函数。
- unique 保证每个回调函数只能被添加一次,即回调函数列表中每个函数都唯一。
- stopOnFalse 如果一个回调函数返回false,则终止调用其他剩余会回调函数。
开发者可以通过以上配置的字符串组合(以空格分隔)初始化回调对象。
var callbacks = $.Callbacks('unique memory'); //回调函数列表中每个函数必须唯一,且要记录上一次调用的参数值
1.2 基本API
Callbacks提供如下API:
- callbacks.add()
向回调函数列表中增加一个回调函数或回调函数集合。 - callbacks.remove()
从回调函数列表中删除一个回调函数或回调函数的集合。 - callbacks.disable()
禁用改回调函数列表,不在执行任何动作。 - callbacks.disabled()
回调函数列表是否被禁用。 - callbacks.empty()
清空回调函数列表。 - callbacks.has()
如果带有参数,则表示该参数是否在回调函数列表中,否则表示回调函数列表是否为空。 - callback.fire()
指定参数调用列表中所有的回调函数。 - callback.fireWith()
指定上下文和参数调用列表中所有的回调函数。 - callback.fired()
回调函数是否被执行过。 - callback.lock()
锁定回调函数列表,使其保持当前的状态不变。 - callback.locked()
回调函数列表是否被锁定。
2. 具体实现
2.1 add和fire/fireWith
从上面的API中已经可以基本看出Callbacks的基本实现方式了,即维护一个回调函数列表(list)和一个参数队列(queue)。每次通过add向list中增加回调函数,然后通过fire/fireWith从queue中取出参数按序执行回调函数。
JQuery的Callbacks模块代码很简单,其核心就是一个内部的fire函数(非api中fire函数,请看下文fire介绍):
// Actual callback list list = [], // Stack of fire calls for repeatable lists stack = !options.once && [], // Fire callbacks fire = function( data ) { memory = options.memory && data; fired = true; firingIndex = firingStart || 0; firingStart = 0; firingLength = list.length; firing = true; for ( ; list && firingIndex < firingLength; firingIndex++ ) { if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { memory = false; // To prevent further calls using add break; } } firing = false; if ( list ) { if ( stack ) { if ( stack.length ) { fire( stack.shift() ); } } else if ( memory ) { list = []; } else { self.disable(); } } }
以上代码摘自JQuery-1.12版本,代码中的list就是回调函数列表,stack就是参数队列queue。可以看出,每次执行fire函数都会遍历list,用传进来的参数调用每个回调函数,如果参数队列不为空,则递归的执行,一直到参数队列取空为止。
我们再看add函数的代码:
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 ); if ( type === "function" ) { if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } } else if ( arg && arg.length && type !== "string" ) { // Inspect recursively add( arg ); } }); })( 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 } else if ( memory ) { firingStart = start; fire( memory ); } } return this; }
add函数会根据参数类型将参数添加到回调函数列表中,即如果参数是一个函数(且要求unique),那么就直接放进回调函数列表中,如果参数是一个类数组,那么就递归调用add函数,将参数中的所有回调函数放进对调函数列表中。
请注意,如果在初始化Callbacks对象时设置了memory,那么在调用add函数的时候,会使用memory记住的参数值调用每一个新加的回调函数。
再看fire和fireWith函数:
// Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( list && ( !fired || stack ) ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; 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; },
这两个函数将参数放进参数队列中,最终都调用内部fire函数将参数传递给回调函数。
2.2 disable和lock
此处要特别说明一下disable和lock的区别,先看这两个函数的实现:
// Have the list do nothing anymore disable: function() { list = stack = memory = undefined; return this; }, // Lock the list in its current state lock: function() { stack = undefined; if ( !memory ) { self.disable(); } return this; },
这两个函数都禁用了回调函数队列,即不能再通过fire/fireWith调用回调函数。但是,如果我们在初始化Callbacks对象的时候,设置了memory的话,那么当回调函数被lock之后,通过add新增的回调函数依然可以使用memory的值调用。
3. 总结
不难看出,整个Callbacks的设计思想就是基于发布订阅(Pub/Sub)的观察者模式。与一般实现方式相比较而言,一个对象不再直接调用另一个对象的方法,而是观察另一个对象的某个特定的任务或活动,这个观察的对象就叫订阅者(Subscriber),被观察的对象就叫发布者(Publisher),当发布者的任务或活动完成时,会通知订阅者。
这种设计模式的主要目的就是为了达到程序之间的松耦合。
- JQuery中的回调对象
- jQuery中的Event对象
- JQuery中的$.when()对象
- jQuery中的ev对象
- JQuery源码解析---jQuery回调对象
- JQuery中的事件对象详解
- Jquery中的控制DOM对象
- 区别jquery中的dom对象与jquery对象
- jQuery对象与Dom对象及jQuery中的选择器
- jQuery对象中的类数组操作
- 使用JQuery获取html中的原始对象
- jquery中的表单对象属性过滤选择器
- jquery查找一个table中的对象
- 关于JQuery中的Deferred延迟操作对象
- 数组对象Jquery真的不难~第五回 JQ中的遍历(遍历中的性能知识点)
- jQuery学习第五课(jquery中的事件和事件对象)
- jquery获取对象在数组对象中的索引值
- jquery中的$对象与原生DOM对象的转换
- swfupload上传文件2038 , 500错误
- 变长参数函数的实现及原理
- 详解辗转相除法求最大公约数,及原理
- Codeforces 801C
- WIN32多线程
- JQuery中的回调对象
- 网上图书商城视频教程day06
- CSS中的视觉格式化模型
- TCP/IP详解--发送ACK和RST的场景
- codeforces #8D Two Friends (二分答案+计算几何)
- 实验五
- jQuery中基本的动画方法
- MFC多线程
- Mac快捷键