前言

本人是一个热爱前端的菜鸟,一直喜欢学习js原生,对于jq这种js库,比较喜欢理解他的实现,虽然自己能力有限,水平很低,但是勉勉强强也算是能够懂一点吧,对于jq源码解读系列,博客园里有很多,推荐大神  艾伦的jq系列,在这里,我仅仅是分享一下我对jq里的Callbacks模块的理解与详细介绍一下我自己仿jq实现的一个callback功能。

功能介绍

jq的Callbacks模块主要是为其他模块提供服务的;

Callbacks的几种状态:

  • once    -- 回调函数只执行一次
  • unique    -- 函数不能重复添加到回调列表中
  • memory    -- 状态记忆,主要用于Deferred中
  • stopOnFalse    -- 遇到return false 终止回调列表继续执行

我自己实现的Callbacks的几个简单的方法

  • add    -- 向对应的回调函数列表添加一个函数
  • fire    -- 触发回调,回调函数列表依次执行函数
  • has    -- 回调函数列表是否存在传入函数
  • clear    -- 清空回调函数列表

整体结构

首先,我们要向得到一个想要的Callbacks模块,需要这样做:

var cb = Callback('memory once')    // 得到一个拥有记忆功能并只执行一次的回调模块

由于我们需要基于一定状态来得到不同的实例,我们可以确定,我们需要一个存储状态的对象

var callbackState = {}

我们给Callback函数传入了'memory once',我们怎么记录这两个状态呢,在这里,仿jq来写的一个函数来实现,如下:

var createCallbackState = function (options) {
var states = options.split(' ')
var obj = {}
for (var i = 0; i < states.length; i++) {
obj[states[i]] = true
}
return obj
}

以上代码,将'memory once' 变成了 {memory: true, once: true},如果状态缓存对象里有这个对象,直接返回,没有的话先创建再返回。

接下来,就是Callback函数的全部代码了,先上代码

var Callback = function (options) {

    var state = callbackState[options]  //获取状态模式
if (!state) {
callbackState[options] = state = createCallbackState(options)
}
var list = [], // 回调函数列表
memory, // 存储是否为 记忆状态
has = function (fn) {
for (var i = 0; i < list.length; i++) {
if (list[i] === fn) {
return true
}
}
return false
},
add = function () {
var i = 0,
args = arguments,
len = args.length
for (; i < len; i++) {
if (state.unique && has(args[i])) { // 如果是unique状态下并回调列表已经拥有该函数,则不添加
continue
}
list.push(args[i])
}
},
fire = function (context, args) {
var i = 0,
len = list.length,
item
for (; i < len; i++) {
item = list[i]
if (item.apply(context,args) === false && state.stopOnFalse) { //如果函数运行返回false,并且是stopOnFalse状态,终止循环
break;
}
}
} return {
add: function () {
add.apply(null,arguments)
// 如果memory模式并且已经拥有了memory信息,接着出发函数
if (state.memory && memory) {
fire(memory[0], memory[1])
list = []
}
},
fire: function (context, args) {
// 如果memory模式,并且list是空,代表触发在添加前,保存memory信息
if (state.memory && !list.length) {
memory = [context, args]
return
}
fire(context,args)
if (state.once) {
this.clear()
}
},
has: function (fn) {
return has(fn)
},
clear: function () {
list = []
}
} }

Callback函数执行后,返回一个对象,然后该对象包含了几个简单的功能。下面我来介绍一下这部分的实现。

首先,如jq一样,我也定义了内部的add, fire, has方法,主要原因是逻辑需要,在返回对象的方法中实现once,memory状态控制,内部的add,fire方法是纯粹的添加和触发函数。

先来看cb.add方法,add方法可以接收多个函数,因此

add.apply(null,arguments)

使用内部的add做添加功能

再往下的一部分的功能是判断这个回调模块是否是memory状态,理解Deferred模块的同学应该知道,该模块是Promise模式,订阅成功或失败状态的回调函数,然后再某一时刻触发他,这个模式便引用了memory状态下的Callback,这个模式有一个奇怪的地方,如果你先发布成功,但是回调列表空空如也,那么程序并不会发布失败,而是等待成功回调函数的加入,一但回调函数加入,立刻执行他。就是如下代码

// 如果memory模式并且已经拥有了memory信息,立刻触发函数
if (state.memory && memory) {
fire(memory[0], memory[1])
list = []
}

提示 : ‘如果你先发布成功,但是回调列表空空如也,那么程序并不会发布失败,而是等待成功回调函数的加入,一但回调函数加入,立刻执行他’ 的理解如下代码

var cb = Callback('memory') // 得到记忆功能的回调模块

cb.fire() // 触发回调队列

cb.add(fn) //添加回调函数,自动执行了!

function fn () {
console.log('fn')
}

如果在非memory状态,以上代码无效。需要再次fire才会执行。

经过上述,fire函数也好理解了,fire可接收两个参数,函数上下文,函数参数数组。

与add中memory状态的代码连串起来,以下代码就是fire时memory状态下的操作

// 如果memory模式,并且list是空,代表触发在添加前,保存memory信息
if (state.memory && !list.length) {
memory = [context, args]
return
}

如果是memory状态,回调列表为空,就保存函数执行上下文和参数数组,等add时立刻执行。

jquery.Callbacks的实现的更多相关文章

  1. jQuery.Callbacks之demo

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

  2. jQuery回调、递延对象总结(上篇)—— jQuery.Callbacks

    前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...

  3. jQuery.Callbacks 源码解读二

    一.参数标记 /* * once: 确保回调列表仅只fire一次 * unique: 在执行add操作中,确保回调列表中不存在重复的回调 * stopOnFalse: 当执行回调返回值为false,则 ...

  4. jQuery源代码学习之四——jQuery.callbacks

    自己实现的callbacks模块相较于jquery源代码中的callbacks模块有所简化,表面上看没有考虑firing这个参数,没有对之进行任何处理,即没有考虑在函数执行过程中,再次调用add,re ...

  5. jQuery.Callbacks之源码解读

    在上一篇jQuery.Callbacks之demo主要说了Callbacks对象初始化常见的选项,这一篇主要分析下Callbacks对象的源代码,对给出两个较为繁琐的demo // String to ...

  6. jQuery回调、递延对象总结(一)jQuery.Callbacks详解

    前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...

  7. jQuery: Callbacks

    jQuery 中提供了一个Callback的工具类Callbacks,它提供了一个Callback Chain.使用它可以在一个chain上来执行相关操作.它也是jQuery中的ajax, Defer ...

  8. jQuery.callbacks 注释

    (function( jQuery ) { // String to Object flags format cache var flagsCache = {}; // Convert String- ...

  9. jQuery 2.0.3 源码分析 回调对象 - Callbacks

    源码API:http://api.jquery.com/jQuery.Callbacks/ jQuery.Callbacks()是在版本1.7中新加入的.它是一个多用途的回调函数列表对象,提供了一种强 ...

随机推荐

  1. Tomcat一个BUG造成CLOSE_WAIT

    之前应该提过,我们线上架构整体重新架设了,应用层面使用的是Spring Boot,前段日子因为一些第三方的原因,略有些匆忙的提前开始线上的内测了.然后运维发现了个问题,服务器的HTTPS端口有大量的C ...

  2. 使用TSQL查询和更新 JSON 数据

    JSON是一个非常流行的,用于数据交换的文本数据(textual data)格式,主要用于Web和移动应用程序中.JSON 使用“键/值对”(Key:Value pair)存储数据,能够表示嵌套键值对 ...

  3. 最新 去掉 Chrome 新标签页的8个缩略图

    chrome的新标签页的8个缩略图实在让人不爽,网上找了一些去掉这个略缩图的方法,其中很多已经失效.不过其中一个插件虽然按照原来的方法已经不能用了,但是稍微变通一下仍然是可以用的(本方法于2017.1 ...

  4. Android调用微信登陆、分享、支付

    前言:用了微信sdk各种痛苦,感觉比qq sdk调用麻烦多了,回调过于麻烦,还必须要在指定包名下的actvity进行回调,所以我在这里写一篇博客,有这个需求的朋友可以借鉴一下,以后自己别的项目有用到也 ...

  5. CRL快速开发框架系列教程五(使用缓存)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  6. JavaScript特性(attribute)、属性(property)和样式(style)

    最近在研读一本巨著<JavaScript忍者秘籍>,里面有一篇文章提到了这3个概念. 书中的源码可以在此下载.我将源码放到了线上,如果不想下载,可以直接访问在线网址,修改页面名就能访问到相 ...

  7. Discuz论坛黑链清理教程

    本人亲测有效,原创文章哦~~~ 论坛黑链非常的麻烦,如果你的论坛有黑链,那么对不起,百度收录了你的黑链,不会自动删除,需要你手动去清理. 什么是黑链 黑链,顾名思义,就是一些赌博网站的外链,这些黑链相 ...

  8. ASP.NET Core 中文文档 第四章 MVC(4.1)Controllers, Actions 和 Action Results

    原文:Controllers, Actions, and Action Results 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:许登洋(Seay) Action 和 acti ...

  9. Hibernate中事务的隔离级别设置

    Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下

  10. 【Java大系】Java快速教程

    感谢原作者:Vamei 出处:http://www.cnblogs.com/vamei Java是面向对象语言.这门语言其实相当年轻,于1995年才出现,由Sun公司出品.James Gosling领 ...