我们经常会这样使用函数回调:
☑ 事件触发通知
☑ 资源加载通知
☑ 定时器延时
☑ ajax、动画通知等等。
以上都是很单一的事件监听回调的处理方式,但是jQuery把回调函数的用法设计成一个更高的抽像,用于解耦与分离变化。
如何理解这个设计?我们看下面的例子。
例子一:
jQuery针对Dom的处理提供了append、prepend、before、after等方法的处理,这几个方法的特征:
1、参数的传递可以是HTML字符串、DOM元素、元素数组或者jQuery对象
2、为了优化性能针对节点的处理需要生成文档碎片
可见几个方法都是需要实现这2个特性的,那么我们应该如何处理?
高层接口:
before: function() {
return this.domManip(arguments, function(elem) {
if (this.parentNode) {
this.parentNode.insertBefore(elem, this);
}
});
},
after: function() {
return this.domManip(arguments, function(elem) {
if (this.parentNode) {
this.parentNode.insertBefore(elem, this.nextSibling);
}
});
},
底层实现:
domManip: function(args, callback) {
// Flatten any nested arrays
args = concat.apply([], args);
// We can't cloneNode fragments that contain checked, in WebKit
if (isFunction ||
//多参数处理
self.domManip(args, callback);
}
if (l) {
//生成文档碎片
fragment = jQuery.buildFragment(args, this[0].ownerDocument, false, this);
callback.call(this[i], node, i);
}
return this;
}
我们观察下jQuery的实现,通过抽象出一个domManip方法,然后在这个方法中处理共性,合并多个参数的处理与生成文档碎片的处理,然后最终把结果通过回调函数返回给每一个调用者。
例子二:
在很多时候需要控制一系列的函数顺序执行。那么一般就需要一个队列函数来处理这个问题。
我们看一段代码:
function Aaron(List, callback) {
setTimeout(function() {
var task;
if (task = List.shift()) {
task(); //执行函数
}
if (List.length > 0) { //递归分解
arguments.callee(List)
} else {
callback()
}
}, 25)
}
//调用
Aaron([
function() {
alert('a')
},
function() {
alert('b')
},
function() {
alert('c')
}
], function() {
alert('callback')
})
// 分别弹出 ‘a’ , ‘b’ ,'c',’callback
传入一组函数参数,靠递归解析,分个执行,其实就是靠setTimeout可以把函数加入到队列末尾才执行的原理,这样的写法就有点就事论事了,聚合对象完全是一个整体,无法再次细分出来,所以我们需要一种方案,用来管理分离每一个独立的对象。
我们换成jQuery提供的方式:
var callbacks = $.Callbacks();
callbacks.add(function() {
alert('a');
})
callbacks.add(function() {
alert('b');
})
callbacks.fire(); //输出结果: 'a' 'b'
是不是便捷很多了,代码又很清晰,所以Callbacks它是一个多用途的回调函数列表对象,提供了一种强大的方法来管理回调函数队列。
那么我们使用回调函数,总的来说弱化耦合,让调用者与被调用者分开,调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件的被调用函数。
请验证,完成请求
由于请求次数过多,请先验证,完成再次请求
打开微信扫码自动绑定
绑定后可得到
使用 Ctrl+D 可将课程添加到书签
举报