jQuery 中 $.Callbacks() 的使用方法
$.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 26
fireWith
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
fireWith 第一个参数是我们的 context,第二个参数是我们需要传递的内容数组,注意了是数组!
empty
清空函数队列
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());//true
lock
锁定回调管理,同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
注意了返回值一定要是false,像undefined、null这种作为返回值是没有效果的
memory
当函数队列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 新的函数依旧会立即执行。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: JavaScript 原型浅析
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论