JavaScript基础CallBack函数(015)
前面提到,函数对象是可以作为参数传递给另一函数的,这时,作为参数的函数如果在内部被执行,那么它就是个回调函数(Callback):
function writeCode(callback) {
// do something...
callback();
// ...
}
function introduceBugs() {
// ... make bugs
}
writeCode(introduceBugs);
在上面的代码里,introduceBugs就作为writeCode的参数,在writeCode函数的执行过程中被调用。因此introduceBugs就是一个回调(CallBack)函数。
下面给出一个更有实际意义的回调函数。假设我们有一个findNodes函数,它可以通过一个复杂的逻辑,在一个很大的数组中找到满足某个条件的所有结点,并返回这些结点:
var findNodes = function () {
var i = 100000, // big, heavy loop
nodes = [], // stores the result
found; // the next node found
while (i) {
i -= 1;
// complex logic here...
nodes.push(found);
}
return nodes;
};
一般来说我们都希望函数的功能单一化,所以这个函数只负责把满足某件的结点找到,并返回。然后我们写另外一个函数hide,可以把给定的一堆结点隐藏,这 个函数接受一个结点的数组作为参数,并把数组中的结点一个一个地隐藏。结合这两个函数,我们就可以完成一个组合功能,即找到一些结点,并把它们隐藏:
var hide = function (nodes) {
var i = 0, max = nodes.length;
for (; i < max; i += 1) {
nodes[i].style.display = "none";
}
}; // executing the functions
hide(findNodes());
看起来挺好。不过这种实现方法的执行效率并不高。这两个函数都需要进行一个很长的循环,则实际上,如果每找到一个满足就条件的结点,就立即把它隐藏,这样效率更高:因为只需要循环1次。为了实践这个想法,但依然把两个任务用不同的函数来实现,我们用回调的方式来做:
// refactored findNodes() to accept a callback
var findNodes = function (callback) {
var i = 100000,
nodes = [],
found; // check if callback is callable
if (typeof callback !== "function") {
callback = false;
} while (i) {
i -= 1; // complex logic here... // now callback:
if (callback) {
callback(found);
} nodes.push(found);
}
return nodes;
};
findNodes这时还是返回满足条件的所有结点,但它也接受一个回调函数,用于给每个满足条件的结点执行一些任务。这个任务就交给回调函数来声明。下面是具体的回调函数hide:
// a callback function
var hide = function (node) {
node.style.display = "none";
}; // find the nodes and hide them as you go
findNodes(hide);
当然,如果hide只服务于findNodes,有时我们不需要给它一个名字,从而把它声明为一个匿名的回调函数:
// passing an anonymous callback
findNodes(function (node) {
node.style.display = "block";
});
回调函数中的this
当回调函数中使用了this,比如,这个回调函数其实是对象myapp中的一个方法paint:
var myapp = {};
myapp.color = "green";
myapp.paint = function (node) {
node.style.color = this.color;
};
这时我们有一个全局的函数findeNodes()接受一个回调函数:
var findNodes = function (callback) {
// ...
if (typeof callback === "function") {
callback(found);
}
// ...
};
这时如果执行 findNodes(myapp.paint),并不能达到预期的结果。因为myapp.paint中的this指针在声明的时候指向的是对象中的属性, 也就是那个对象本身,但当myapp.paint作为回调函数在全局的函数findNodes时执行是,this指针在执行期间指向的就变成了全局的 this了(如果在浏览器中,就是dom对象)。
解决方法是把回调函数所属的对象也一并传递给findNodes,然后在执行回调函数时指定它所属的对象:
findNodes(myapp.paint, myapp);
所以findNodes修改为这样:
var findNodes = function (callback, callback_obj) {
//...
if (typeof callback === "function") {
callback.call(callback_obj, found);
}
// ...
};
这样看起来有点啰嗦,因为对象的名字在参数列表里出现了两次。我们也可以把这个回调函数的名字用字符串的方式传递:
findNodes("paint", myapp);
这里findNodes就相应的修改为:
var findNodes = function (callback, callback_obj) {
if (typeof callback === "string") {
callback = callback_obj[callback];
}
//...
if (typeof callback === "function") {
callback.call(callback_obj, found);
}
// ...
};
最新文章
- 用户 &#39;IIS APPPOOL\DefaultAppPool&#39; 登录失败。
- centos linux安装telnet 过程及问题(源于内部tomcat网站,外部无法访问)
- 查看Eclipse中的jar包的源代码:jd-gui.exe
- jQuery前端验证多种方式
- Object-C 内存管理及对象
- VirtualBox虚拟机安装MSDOS和MINIX2.0.0双系统
- Read ListViewItem content from another process z
- HDOJ-ACM1004(JAVA)
- C++类实现AVL树
- linux定时执行python脚本
- JVM指令集(指令码、助记符、功能描述)(转)
- 已知从BUF开始存放了10个字类型有符号数据,编程求出这10个数中的最大数和最小数(将最大数存入MAX字单元、最小数存入MIN字单元),并将其以10进制数的形式在屏幕上显示出来。
- G彩娱乐网一个程序员到一个销售高手的心路历程
- 【转载】OAuth2 流程
- 17.10.28&;29
- 我的CSS
- 爬虫协议 Tobots
- python 10道面试陷阱题目
- sklearn-数据预处理scale
- 如何正确地使用android中的progressdialog