1 向回调函数传递额外的参数
大部分回调函数都有传递给它们的自动函数,如错误或结果缓冲区。使用回调函数时,常见一个问题:如何从调用函数给回调函数传递额外的参数。一个方法就是在一个匿名函数中实现该参数,然后用来自匿名函数的参数调用回调函数。
示例:
var events = require('events');
var util = require('util');
function CarShow() {
this.showCar = function (make) {
this.emit('showed', make);
}
}
util.inherits(CarShow, events.EventEmitter);
function logCar(make) {
console.log('我看见了一辆%s', make);
}
function logColorCar(make, color) {
console.log('我看见了一辆%s', color, make);
}
var carShow = new CarShow();
carShow.on('showed', logCar);
carShow.on('showed', function (make) {
var colors = ['白色', '黑色', '红色', '蓝色'];
var color = colors[Math.floor(Math.random() * 4)];
logColorCar(make, color);
});
carShow.showCar("奔驰");
输出:
我看见了一辆奔驰
我看见了一辆白色 奔驰
可以看到定义的第二个事件处理程序用了一个匿名函数。随机选择的颜色被传递给函数logColorCar调用。
2 在异步回调中实现闭包
闭包表示一个变量被绑定到一个函数的作用域,但不绑定到它的父函数的作用域(也可以简单理解成:闭包内的函数可以使用父函数的变量,但是父函数不可以使用它的变量)。
如果某个函数需要访问父函数的作用域的变量,就需要闭包。
function logCar(msg, callback) {
process.nextTick(function () {//这样才能异步回调
callback(msg);
});
}
var cars = ['奔驰', '宝马', '大众', '红旗'];
for (var index in cars) {
var msg = cars[index];
logCar(msg, function () {
console.log(msg);
})
}
for (var index in cars) {
var msg = cars[index];
(function (index) {
var msg = cars[index];
logCar(msg, function () {
console.log(msg);
})
})(index);
}
输出:
红旗
红旗
红旗
红旗
奔驰
宝马
大众
红旗
在前端,可能会有这样的需求:有若干方块,当鼠标移入某个方块上时,这个方块及它之前的所有方块要发生一些样式上的变化。这个函数的实现便需要闭包:
var oDivs = document.getElementsByTagName('div');
for (var i = 0; i < oDivs.length; i++) {
(function (index) {
oDivs[i].onmouseover = function () {
for (var j = 0; j <= index; j++) {
oDivs[j].style.background = "pink";
}
}
oDivs[i].onmouseout = function () {
for (var j = 0; j <= index; j++) {
oDivs[j].style.background = "white";
}
}
})(i);
}
3 链式回调
使用异步函数时,如果两个函数都在事件队列上,则无法保证它们的执行顺序。解决办法:让来自异步函数的回调再次调用该函数,直到没有工作要做,以执行链式回调。这样异步函数在事件队列上不会超过一次。
function logCar(car, callback) {
console.log("我看见了一辆%s", car);
if (cars.length) {
process.nextTick(function () {
callback();
});
}
}
function logCars(cars) {
var car = cars.pop();
logCar(car, function () {
logCars(cars);
})
}
var cars = ['奔驰', '宝马', '大众', '红旗'];
logCars(cars);
输出:
我看见了一辆红旗
我看见了一辆大众
我看见了一辆宝马
我看见了一辆奔驰