摘要:参考以下对比不添加参数添加参数相同的函数不会被重复添加到内部队列中内部队列里的函数是依次执行的,当某个函数的返回值是时,停止继续执行剩下的函数。
前言
$.Callbacks用来管理函数队列。采用了观察者模式,通过add添加操作到队列当中,通过fire去执行这些操作。实际上$.Callbacks是1.7版本从$.Deferred对象当中分离出来的,主要是实现$.Deferred功能。
API $.Callbacks我们通过调用$.Callbacks获取到一个callback实例,如下
var cb = $.Callbacks();
看到Callbacks首字母大写,有些人可能会觉得一般只有对象才会这样,因此需要new一个实例,如下
var cb = new $.Callbacks();
实际上这两种方式都可以,因为Callbacks函数返回值是一个对象,为什么会这样?看下面一组对比
function Cons() { this.name = "this.name"; return { name: "obj.name" }; } console.log(Cons().name);//obj.name console.log(new Cons().name);//obj.name function Cons() { this.name = "this.name"; return "str.name"; } console.log(Cons());//str.name console.log(new Cons().name);//this.name
当函数的返回值是一个对象时(null除外),new和直接调用两者的返回值是一样的。但是需要注意了,两者的this指向是不一样的。为了尽可能的节省代码和避免混乱我们还是统一采用var cb = $.Callbacks();的方式去调用。
像这种先调用获取到实例,然后通过实例进行一系列的操作,很明显利用了闭包特性。
add向内部队列添加函数,总有三种参数形式
单个函数参数var cb = $.Callbacks(); cb.add(function () { console.log("add one"); });多个函数参数
var cb = $.Callbacks(); cb.add(function () { console.log("add one"); }, function () { console.log("add two"); });数组参数
var cb = $.Callbacks(); cb.add([ function () { console.log("add one"); }, function () { console.log("add two"); } ]);fire
依次执行队列里的函数
var cb = $.Callbacks(); cb.add([ function () { console.log("add one"); }, function () { console.log("add two"); } ]); cb.fire(); //add one //add two
fire的参数会传递给我们添加的函数,例如
var cb = $.Callbacks(); cb.add(function (name, age) { console.log(name, age); }); cb.fire("Jacky", 26);//Jacky 26fireWith
fire调用的时候,我们添加函数当中的this指向我们的Callbacks实例,例如
var cb = $.Callbacks(); cb.add(function () { console.log(this === cb); }); cb.fire();//true
fireWith就是改变我们添加函数的context,即this指向,例如
var cb = $.Callbacks(); var obj = { name: "objName" }; cb.add(function (age) { console.log(this.name, age); }); cb.fireWith(obj, [26]);//objName 26
emptyfireWith第一个参数是我们的context,第二个参数是我们需要传递的内容数组,注意了是数组!
清空函数队列
var cb = $.Callbacks(); cb.add(function () { console.log("add one"); }); cb.empty(); cb.fire();has
判断函数队列中是否存在某个函数
var cb = $.Callbacks(); function demo() { console.log("demo"); } cb.add(demo); console.log(cb.has(demo));//true
函数传递的都是引用,千万别出现以下的低级错误
var cb = $.Callbacks(); cb.add(function () { console.log("demo"); }); cb.has(function () { console.log("demo"); });remove
从内部队列中移除某些函数
var cb = $.Callbacks(); function demo1() { console.log("demo1"); } function demo2() { console.log("demo2"); } cb.add(demo1, demo2); cb.remove(demo1, demo2); cb.fire();disable
禁用回调列表。这种情况会清空函数队列,禁用核心功能。意味着这个回调管理报废了。
var cb = $.Callbacks(); cb.add(function () { console.log("add"); }); cb.disable(); cb.fire();disabled
回调管理是否被禁用
var cb = $.Callbacks(); cb.add(function () { console.log("add"); }); cb.disable(); console.log(cb.disabled());//truelock
锁定回调管理,同disable,唯一的差别会在下面表述
locked回调管理是否被锁
fired回调队列是否执行过
var cb = $.Callbacks(); cb.add(function () { console.log("add"); }); cb.fire();//add console.log(cb.fired());//true$.Callbacks()
$.Callbacks通过字符串参数的形式支持4种及以上的特定功能。很明显的一个工厂模式。
once函数队列只执行一次。参考以下对比
//不添加参数 var cb = $.Callbacks(); cb.add(function () { console.log("add"); }); cb.fire();//add cb.fire();//add //添加参数 var cb = $.Callbacks("once"); cb.add(function () { console.log("add"); }); cb.fire();//add cb.fire();
函数队列执行过以后,就不会在执行了,无论调用fire多少次。
unique往内部队列添加的函数保持唯一,不能重复添加。参考以下对比
//不添加参数 var cb = $.Callbacks(); function demo() { console.log("demo"); } cb.add(demo, demo); cb.fire(); //demo //demo //添加参数 var cb = $.Callbacks("unique"); function demo() { console.log("demo"); } cb.add(demo, demo); cb.fire();//demo
相同的函数不会被重复添加到内部队列中
stopOnFalse内部队列里的函数是依次执行的,当某个函数的返回值是false时,停止继续执行剩下的函数。参考以下对比
//不添加参数 var cb = $.Callbacks(); cb.add([ function () { console.log("add one"); }, function () { console.log("add two"); } ]); cb.fire(); //add one //add two //添加参数 var cb = $.Callbacks("stopOnFalse"); cb.add([ function () { console.log("add one"); return false; }, function () { console.log("add two"); } ]); cb.fire();//add one
memory注意了返回值一定要是false,像undefined、null这种作为返回值是没有效果的
当函数队列fire或fireWith一次过后,内部会记录当前fire或fireWith的参数。当下次调用add的时候,会把记录的参数传递给新添加的函数并立即执行这个新添加的函数。看个例子
var cb = $.Callbacks("memory"); cb.add(function (name) { console.log("one", name); }); cb.fire("Jacky");//first Jacky cb.add(function (name) { console.log("two", name); });//two Jacky
例如公司领导在9点的时候发了封邮件,要求大家提交自己的年终终结,这就相当于fire操作了,在公司里的员工收到邮件后,立马提交了。小李由于请假,下午才过来,看到邮件后也提交了自己的年终总结。不需要领导再次发送邮件提醒。
小结fire或fireWith一定要在disabled或lock前先执行一遍,memory才会起作用
这四种基本类型可以相互组合起来使用,例如$.Deferred就使用了once和memory的组合。
jQuery.Callbacks("once memory")disable和lock的区别
两者唯一的区别就是添加了memory参数,看一下对比
var cb = $.Callbacks("memory"); cb.add(function () { console.log("one"); }); cb.fire(); cb.disable(); //cb.lock(); cb.add(function () { console.log("two"); });
毫无疑问,disable就是禁用所有功能,无论添加什么参数。而在memory的情况下,fire过后在lock,继续add新的函数依旧会立即执行。
总结$.Callbacks在一百多行的代码里就用到了两种设计模式,确实经典。当然了这都是纯属个人见解。由于平时用的很少,很遗憾没有举出代表性的例子供大家参考,毕竟我辈的目标是学以致用。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/91607.html
摘要:的支持的方法有几个主要的,和,比如官方有一个例子这两个作为函数调用的生成从基本可以看出,函数生成了一个对象,这个对象的方法是添加回调函数,而方法则是执行回调函数。 欢迎来我的专栏查看系列文章。 讲真,Sizzle 的源码真的太压抑了,以至于写 Sizzle 文章的这段时间里都非常的痛苦,刚开始觉得它还挺有意思的,越到后面越觉得代码很难读懂,烦。 寒假也过完了,在家里待了两周的时间,感觉...
摘要:作为此时不存在,直接从数据缓存中获取并返回。作用是触发中的回调函数,的表示只让触发一次后,就需要清理,表示是将清空成空数组还是空字符。 showImg(https://segmentfault.com/img/remote/1460000019558449); 前言:queue()方法和dequeue()方法是为 jQuery 的动画服务的,目的是为了允许一系列动画函数被异步调用,但不...
摘要:我们称为回调对象,它内部会维护一个数组,我们可以向其中添加若干个回调函数,然后在某一条件下触发执行。第一次之后,再次新的回调函数时,自动执行回调。当前面的回调函数返回时,终止后面的回调继续执行。 最近懒癌发作,说好的系列文章,写了一半,一直懒得写,今天补上一篇。 Deferred 我们在使用promise对象时,总会提到一个与它关系密切的对象——Deferred。其实Deferred没...
摘要:回调队列对象,用于构建易于操作的回调函数集合,在操作完成后进行执行。对象对象,用于管理回调函数的多用途列表。如果传入一个延迟对象,则返回该对象的对象,可以继续绑定其余回调,在执行结束状态之后也同时调用其回调函数。 在工作中我们可能会把jQuery选择做自己项目的基础库,因为其提供了简便的DOM选择器以及封装了很多实用的方法,比如$.ajax(),它使得我们不用操作xhr和xdr对象,直...
阅读 2287·2023-04-25 14:22
阅读 3733·2021-11-15 18:12
阅读 1293·2019-08-30 15:44
阅读 3214·2019-08-29 15:37
阅读 637·2019-08-29 13:49
阅读 3454·2019-08-26 12:11
阅读 865·2019-08-23 18:28
阅读 1580·2019-08-23 14:55