一、什么是回调函数(Callback)?
回调函数(Callback Function)是指一个函数被作为参数传递给另一个函数,并在特定事件发生或操作完成时执行。
可以通俗地理解为一种“委托”机制。
在JavaScript中,回调函数的应用非常广泛,例如:
异步操作:如定时器、AJAX请求等。
数组方法:如map、filter、reduce等高阶函数。
事件处理:如DOM事件监听。
二、一个简单例子
同步操作的例子:
// 模拟点餐函数
function orderFood(dish, callback) {console.log(`你点了 ${dish}`);// 厨房开始准备食物callback(dish);
}// 模拟厨房准备食物的回调函数
function prepareFood(dish) {console.log(`厨房正在准备 ${dish}`);
}// 用户点餐并委托厨房准备食物
orderFood('汉堡', prepareFood);//输出 你点了 汉堡 厨房正在准备 汉堡
在这个例子中,prepareFood 是一个回调函数,它被传递给 orderFood 函数。当用户点餐后,orderFood 函数调用 prepareFood 函数来通知厨房开始准备食物。
匿名回调函数
// 模拟点餐函数
function orderFood(dish, callback) {console.log(`你点了 ${dish}`);// 厨房开始准备食物callback(dish);
}// 用户点餐并委托厨房准备食物
orderFood('汉堡', function prepareFood(dish) {console.log(`厨房正在准备 ${dish}`);
});//输出 你点了 汉堡 厨房正在准备 汉堡
异步操作例子
假设准备食物需要一些时间,我们可以使用 setTimeout 来模拟异步操作。
// 模拟点餐函数
function orderFood(dish, callback) {console.log(`你点了 ${dish}`);// 模拟厨房准备食物需要2秒setTimeout(function() {callback(dish);}, 2000);
}// 模拟厨房准备食物的回调函数
function prepareFood(dish) {console.log(`厨房正在准备 ${dish}`);
}// 用户点餐并委托厨房准备食物
orderFood('汉堡', prepareFood);//输出
//你点了 汉堡
// 等待2秒后
//厨房正在准备 汉堡
在这个例子中,orderFood 函数使用 setTimeout 来模拟厨房准备食物需要2秒的时间。在2秒后,callback(dish) 被调用,即 prepareFood(dish) 被执行。
三、回调函数的特点
1、延迟执行(不会立即执行)
回调函数作为参数传递给一个函数的时候,传递的只是函数的定义并不会立即执行。在某个事件发生或操作完成后才被调用。这使得它们非常适合处理异步操作,如网络请求、文件读取、定时器等。
2、支持闭包
回调函数可以捕获其定义时的上下文(即闭包),这使得它们可以访问外部函数的变量和状态。
function createCounter() {let count = 0;return function() {count++;console.log(count);};
}const counter = createCounter();
counter(); // 输出: 1
counter(); // 输出: 2
四、回调函数中this指向问题
1、this关键字:
一个指针型变量,它指向当前函数的运行环境。即所在函数的调用者。
无论函数原本属于谁,从哪来的,判断this的唯一依据就是此刻函数的执行由那个对象调用的。
2、回调函数的this指向
注意在回调函数调用时this的执行上下文并不是回调函数定义时的那个上下文,而是调用它的函数所在的上下文。
3、解决方法:
以下面代码举例
function createData(callback) {callback();
}var obj = {data: 100,tool: function() {createData(function(n) {console.log(this, 1111); // window 1111});}
};obj.tool();
1、使用箭头函数
箭头函数不绑定自己的 this,它会捕获其所在上下文的 this 值。
var obj = {data: 100,tool: function() {createData(() => {console.log(this, 1111); // obj 1111});}};
2、使用 bind 方法
使用 bind 方法显式地绑定 this。
var obj = {data: 100,tool: function() {createData(function(n) {console.log(this, 1111); // obj 1111}.bind(this));}};
3、使用 var self = this
在外部保存 this 的引用。
var obj = {data: 100,tool: function() {var self = this;createData(function(n) {console.log(self, 1111); // obj 1111});}};
回调函数中的 this 指向问题通常是因为回调函数在全局作用域中被调用。可以通过以下几种方式解决:
箭头函数:捕获其所在上下文的 this 值。
bind 方法:显式地绑定 this。
var self = this:在外部保存 this 的引用。
选择哪种方法取决于你的具体需求和个人偏好。箭头函数通常是最简洁和推荐的方式。
五、回调函数其他例子
1、异步操作
setTimeout(function() {console.log('3秒后执行');
}, 3000);
在这个例子中,function() { console.log('3秒后执行'); } 就是一个回调函数,在3秒后由 setTimeout 调用。
2、数组方法
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(function(number) {return number * 2;
});
console.log(doubled); // 输出: [2, 4, 6, 8]
这里的 function(number) { return number * 2; } 是一个回调函数,用于对数组中的每个元素进行操作。
3、事件处理
document.getElementById('myButton').addEventListener('click', function() {console.log('按钮被点击了');
});
推荐博文:JS中的 回调函数(callback)_js回调函数-CSDN博客