核心原则 :
所有回调函数的参数是"按位置绑定"的,顺序严格固定,不可更改。你不能通过参数名来"选择"接收哪个参数,位置决定一切。
📌 一、参数传递的核心机制:位置绑定(Positional Binding)
在 JavaScript 中,函数调用时的参数传递是 按"位置"而非"名字" 进行的。
🔍 示例说明
function myCallback(a, b, c) {
console.log('a:', a);
console.log('b:', b);
console.log('c:', c);
}
// 调用时:
myCallback("第一个", "第二个", "第三个");
a: 第一个
b: 第二个
c: 第三个
👉 无论你把参数叫做 a
、b
、c
还是 xhr
、settings
、data
,系统只认"第几个"。
✅ 二、$.ajax
各回调函数参数详解(严格按位置)
1️⃣ beforeSend(xhr, settings)
位置 | 参数名(可自定义) | 实际值 | 类型 | 是否可省略 |
---|---|---|---|---|
1st | 第一个参数 | XMLHttpRequest 对象 |
Object |
✅ 可省略(但位置必须空着) |
2nd | 第二个参数 | 请求配置对象 | Object |
✅ 可省略 |
🔹 位置不可变!
- 第一个参数永远是
xhr
- 第二个参数永远是
settings
- 即使你写成
function(settings, xhr)
,第一个接收到的还是xhr
❌ 错误示例(你以为的 settings
其实是 xhr
)
beforeSend: function(settings) {
console.log(settings.type); // ❌ 报错!settings 实际上是 xhr 对象
}
✅ 正确写法
beforeSend: function(xhr, settings) {
// 明确使用两个参数
if (settings.type !== 'GET') {
xhr.setRequestHeader('X-CSRFToken', getCookie('csrftoken'));
}
}
// 如果只想用 settings,必须写两个参数,第一个占位
beforeSend: function(_, settings) {
// _ 接收 xhr(不用),settings 接收第二个参数
if (settings.url.includes('/admin/')) {
console.log('这是管理员请求');
}
}
2️⃣ success(data, textStatus, xhr)
位置 | 参数名(可自定义) | 实际值 | 类型 |
---|---|---|---|
1st | 第一个参数 | 服务器返回的数据(已解析) | Object/String |
2nd | 第二个参数 | 状态描述(通常是 "success" ) |
String |
3rd | 第三个参数 | XMLHttpRequest 对象 |
Object |
🔹 位置不可变!
- 无论你叫它
data
、result
、response
,第一个参数永远是返回的数据 textStatus
永远是第二个xhr
永远是第三个
✅ 示例
success: function(data, status, xhr) {
// data = 返回的 JSON 或文本
// status = "success"
// xhr = 可读取响应头
$('#result').html(data.html);
}
❌ 错误:想只用 xhr
success: function(xhr) {
// ❌ 错!你拿到的是 data,不是 xhr!
console.log(xhr.status); // ❌ 报错,data 没有 .status
}
✅ 正确:只用 xhr
success: function(_, __, xhr) {
// _ 接 data, __ 接 status, xhr 接第三个
console.log('响应头:', xhr.getAllResponseHeaders());
}
3️⃣ error(xhr, textStatus, errorThrown)
位置 | 参数名(可自定义) | 实际值 | 类型 |
---|---|---|---|
1st | 第一个参数 | XMLHttpRequest 对象 |
Object |
2nd | 第二个参数 | 错误类型("timeout" , "error" 等) |
String |
3rd | 第三个参数 | HTTP 状态文本(如 "Not Found" ) |
String |
🔹 位置不可变!
- 第一个参数永远是
xhr
(不是errorThrown
!) - 第二个是
textStatus
- 第三个是
errorThrown
✅ 正确示例
error: function(xhr, status, error) {
if (xhr.status === 404) {
alert('页面不存在');
} else if (status === 'timeout') {
alert('请求超时');
}
}
❌ 常见误区
error: function(errorThrown) {
// ❌ 错!你拿到的是 xhr 对象,不是错误文本!
alert(errorThrown); // ❌ 显示 [object XMLHttpRequest]
}
4️⃣ complete(xhr, textStatus)
位置 | 参数名(可自定义) | 实际值 | 类型 |
---|---|---|---|
1st | 第一个参数 | XMLHttpRequest 对象 |
Object |
2nd | 第二个参数 | 最终状态("success" , "error" 等) |
String |
🔹 位置不可变!
- 第一个永远是
xhr
- 第二个永远是
textStatus
✅ 正确用法
complete: function(xhr, status) {
$('#loading').hide(); // 隐藏加载动画
console.log('请求结束,状态:', status);
}
🧩 三、参数省略的正确方式
想要的效果 | 正确写法 | ❌ 错误写法 |
---|---|---|
只用 settings (beforeSend ) |
function(_, settings) |
function(settings) |
只用 xhr (success ) |
function(_, __, xhr) |
function(xhr) |
只用 errorThrown (error ) |
function(_, __, errorThrown) |
function(errorThrown) |
完全不用参数 | function(){} |
(无) |
⚠️ 永远记住:省略参数 ≠ 改变顺序,系统永远按固定位置传参。
🎯 四、总结:参数位置表
回调函数 | 第1个参数 | 第2个参数 | 第3个参数 |
---|---|---|---|
beforeSend |
xhr |
settings |
--- |
success |
data |
textStatus |
xhr |
error |
xhr |
textStatus |
errorThrown |
complete |
xhr |
textStatus |
--- |
🚀 五、一句话终极总结
$.ajax
的回调参数就像"快递柜的格子":
- 第1格永远放
xhr
- 第2格永远放
settings
/textStatus
- 第3格放
errorThrown
或xhr
你不能说"我要第3格的东西",然后只开一个格子------
你开的第一个格子,永远是第1格。
位置决定内容,名字只是标签。