网络宝典
第二套高阶模板 · 更大气的阅读体验

回调函数传参的常见用法与技巧

发布时间:2025-12-12 19:45:22 阅读:132 次

写代码时,经常会遇到需要“事情办完后通知我”的场景。比如发个网络请求,等结果回来再处理数据;或者点个按钮,等用户操作后再执行一段逻辑。这种“事后通知”的机制,通常靠回调函数实现。

但问题来了:光调用一个函数不够用,我们往往还得把一些上下文信息一起传进去。这时候就得给回调函数传参。

直接传参的误区

新手常犯的一个错误是这样写:

setTimeout(console.log('Hello'), 1000);

本意是想一秒钟后打印 Hello,结果页面一加载就立刻执行了。因为这里不是在传函数,而是在执行函数。正确做法是传一个函数引用。

使用匿名函数包装

最简单直接的方式,是用一个匿名函数把调用包一层:

setTimeout(function() {
    console.log('Hello');
}, 1000);

这样 setTimeout 接收到的是一个函数,等时间到了才会执行里面的内容。如果要传变量,也很直观:

var name = '张三';
setTimeout(function() {
    console.log('你好,' + name);
}, 1000);

这里的 name 就通过闭包被记住了。

利用 bind 方法绑定参数

Function.prototype.bind 可以预设函数的 this 和参数。比如有这样一个回调函数:

function greet(greeting, name) {
    console.log(greeting + ',' + name + '!');
}

我们可以预先固定第一个参数:

var sayHi = greet.bind(null, 'Hi');
sayHi('小明'); // 输出:Hi,小明!

在事件监听中也常用到:

button.addEventListener('click', handleClick.bind(null, userId));

这样点击时就能拿到对应的 userId,不用去查 DOM 或者依赖闭包。

箭头函数简化传参

ES6 的箭头函数让包装更简洁:

setTimeout(() => console.log('五秒后见'), 5000);

带参数的情况也干净利落:

users.forEach(user => {
    setTimeout(() => notifyUser(user.id), 1000);
});

每个循环里的 user 都被正确捕获,不会出现常见的闭包陷阱。

实际应用场景

假设你在做一个上传文件的功能,每传一个文件,等完成后要提示用户。你可以这样设计:

function uploadFile(file, onSuccess) {
    // 模拟上传
    setTimeout(() => {
        onSuccess(file.name);
    }, 2000);
}

uploadFile(myFile, function(fileName) {
    alert(fileName + ' 上传成功!');
});

onSuccess 就是一个带参的回调,文件名从上传函数里传回给了调用方。

这种模式在异步编程里非常普遍,理解好回调传参,才能写出清晰可靠的逻辑。