JQuery中的回调对象
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中的回调对象的更多相关文章
- javascript 学习笔记之JQuery中的Deferred对象
Deffered是Jquery中的一个非常重要的对象,从1.5版本之后,Jquery中的ajax操作都基于Deffered进行了重构,这个对象的处理模式就像其他Javascript框中的Promise ...
- 转: jquery中ajax回调函数使用this
原文地址:jquery中ajax回调函数使用this 写ajax请求的时候success中代码老是不能正常执行,找了半天原因.代码如下 $.ajax({type: 'GET', url: " ...
- jquery中ajax回调函数使用this
今天在写ajax请求的的时候success中代码老是不能正常执行,找了半天的原因,代码如下: 1 $.ajax({type: 'GET', 2 url: url, 3 data: oData, 4 s ...
- jquery中each遍历对象和数组示例
通用遍历方法,可用于遍历对象和数组.$().each(),回调函数拥有两个参数: 第一个为对象的成员或数组的索引,第二个为对应变量或内容.如需退出each循环可使回调函数返回false 现有如下两个s ...
- jQuery中的deferred对象和extend方法
1⃣️deferred对象 deferred对象是jQuery的回调函数解决方案,它是从jQuery1.5.0版本开始引入的功能 deferred对象的方法 (1) $.Deferred() 生成一个 ...
- jQuery中deferred的对象使用
什么是deferred对象 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作.其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是 ...
- jQuery中的事件对象(八)
Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 一.事件对象基本认识 1. 什么时候会产生Event 对象呢? 例如: 当用户单击某个元素的时 ...
- js和jquery中的遍历对象和数组(forEach,map,each)
arr[].forEach(function(value,index,array){ //do something }) 参数:value数组中的当前项,index当前项的索引,array原始数组: ...
- jquery 中的回调函数,回调函数(callback)是什么?
知乎上果然大牛比较多 大神解释如下: 你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货.在这个例子里, ...
随机推荐
- [图形学] Chp17 OpenGL光照和表面绘制函数
这章学了基本光照模型,物体的显示受到以下效果影响:全局环境光,点光源(环境光漫反射分量,点光源漫反射分量,点光源镜面反射分量),材质系数(漫反射系数,镜面反射系数),自身发光,雾气效果等.其中点光源有 ...
- 流行框架(angularj基础)
- hdfs文件系统架构详解
hdfs文件系统架构详解 官方hdfs分布式介绍 NameNode *Namenode负责文件系统的namespace以及客户端文件访问 *NameNode负责文件元数据操作,DataNode负责文件 ...
- 微信公众号调用JS-SDK
坑:先设置js接口安全域名,在公众号设置-功能设置-js接口安全域名中设置 授权登录功能需要在开发者中心页配置授权回调域名 文档:http://mp.weixin.qq.com/wiki/7/aaa1 ...
- jsp: c:foreach 输出序号
关键在于<c:forEach>的varStatus属性,具体代码如下: <table width="500" border="0" cells ...
- nodejs之url模块
鄙人初步学习nodejs,目前在读<nodejs入门>这一本书,书很小,但是让我知道了如何用nodejs创建一个简单的小项目.例如如何创建一个服务器啦,例如http.createServe ...
- 用Node.JS+MongoDB搭建个人博客(安装环境)(一)
Node.JS是什么? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效. Nod ...
- Multimodal —— 看图说话(Image Caption)任务的论文笔记(一)评价指标和NIC模型
看图说话(Image Caption)任务是结合CV和NLP两个领域的一种比较综合的任务,Image Caption模型的输入是一幅图像,输出是对该幅图像进行描述的一段文字.这项任务要求模型可以识别图 ...
- 机器学习 —— 基础整理(八)循环神经网络的BPTT算法步骤整理;梯度消失与梯度爆炸
网上有很多Simple RNN的BPTT(Backpropagation through time,随时间反向传播)算法推导.下面用自己的记号整理一下. 我之前有个习惯是用下标表示样本序号,这里不能再 ...
- MySQL学习笔记(一):SQL基础
定义:SQL即Structure Query Language(机构化查询语言)的缩写,是使用关系数据库的应用语言. 包括三个类别: (1):DDL(Data Definition Language) ...