概览
$.Callbacks() 是 jQuery 提供的一个多用途回调列表管理对象。它提供了一种强大而灵活的方式来管理函数队列,允许添加、移除、触发和锁定回调函数。这个核心工具常被用于实现观察者模式、事件系统以及作为 $.Deferred 等高级异步机制的基础。深入理解 jQuery回调函数 的管理机制,对于编写模块化、解耦的代码以及掌握 jQuery 内部工作原理具有重要意义。
jQuery.Callbacks() 基础
语法
jQuery.Callbacks( flags )flags:一个可选的字符串,由空格分隔的标志位组成,用于改变回调列表的行为。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks 基本示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fireBtn">触发回调</button>
<div id="result"></div>
<script>
var callbacks = $.Callbacks();
callbacks.add(function(msg) {
$('#result').append('<p>回调1: ' + msg + '</p>');
});
callbacks.add(function(msg) {
$('#result').append('<p>回调2: ' + msg + '</p>');
});
$('#fireBtn').on('click', function() {
callbacks.fire('按钮被点击');
});
</script>
</body>
</html>标志位 Flags
标志位字符串用于配置回调列表的行为。可以组合使用,例如 "once memory"。
| 标志位 | 描述 |
|---|---|
once | 回调列表仅能被触发一次。再次调用 .fire() 或 .fireWith() 将无效。 |
memory | 回调列表会记住上一次触发的参数。当新增回调时,会立即使用这些记忆的参数调用该回调。 |
unique | 允许在回调列表中每个回调函数只能被添加一次,防止重复添加。 |
stopOnFalse | 如果某个回调函数返回 false,则会中断后续回调的执行。 |
once
语法
var callbacks = $.Callbacks('once');示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks once 示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fireOnceBtn">触发(仅一次)</button>
<div id="log"></div>
<script>
var callbacks = $.Callbacks('once');
callbacks.add(function() {
$('#log').append('<p>回调被执行</p>');
});
$('#fireOnceBtn').on('click', function() {
callbacks.fire(); // 只有第一次点击会有效
callbacks.fire(); // 后续点击无效果
});
</script>
</body>
</html>memory
语法
var callbacks = $.Callbacks('memory');示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks memory 示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fireMemoryBtn">触发并记住参数</button>
<button id="addLaterBtn">添加后加回调</button>
<div id="output"></div>
<script>
var callbacks = $.Callbacks('memory');
callbacks.add(function(value) {
$('#output').append('<p>初始回调: ' + value + '</p>');
});
$('#fireMemoryBtn').on('click', function() {
callbacks.fire('第一次触发');
});
$('#addLaterBtn').on('click', function() {
callbacks.add(function(value) {
$('#output').append('<p>后加回调: ' + value + '</p>');
});
});
</script>
</body>
</html>unique
语法
var callbacks = $.Callbacks('unique');示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks unique 示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="addBtn">添加回调</button>
<button id="fireBtn">触发</button>
<div id="message"></div>
<script>
var callbacks = $.Callbacks('unique');
var fn = function() {
$('#message').append('<p>回调执行</p>');
};
$('#addBtn').on('click', function() {
callbacks.add(fn); // 多次点击也只会添加一次
$('#message').append('<p>尝试添加回调</p>');
});
$('#fireBtn').on('click', function() {
callbacks.fire();
});
</script>
</body>
</html>stopOnFalse
语法
var callbacks = $.Callbacks('stopOnFalse');示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks stopOnFalse 示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fireBtn">触发</button>
<div id="trace"></div>
<script>
var callbacks = $.Callbacks('stopOnFalse');
callbacks.add(function() {
$('#trace').append('<p>回调 1 执行</p>');
return true; // 继续
});
callbacks.add(function() {
$('#trace').append('<p>回调 2 执行,返回 false 停止</p>');
return false;
});
callbacks.add(function() {
$('#trace').append('<p>回调 3 不会执行</p>');
});
$('#fireBtn').on('click', function() {
callbacks.fire();
});
</script>
</body>
</html>组合使用
多个标志位可以组合使用,例如 "once memory" 创建一个只触发一次但会记住参数的回调列表。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks 组合标志示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fireBtn">触发(仅一次)</button>
<button id="addBtn">添加后加回调</button>
<div id="result"></div>
<script>
var callbacks = $.Callbacks('once memory');
callbacks.fire('初始化参数'); // 即使触发后添加回调也会立即执行
$('#fireBtn').on('click', function() {
callbacks.fire('再次触发'); // 不会生效
});
$('#addBtn').on('click', function() {
callbacks.add(function(msg) {
$('#result').append('<p>后加回调收到: ' + msg + '</p>');
});
});
</script>
</body>
</html>方法详解
add()
语法
callbacks.add( callbacks )
callbacks.add( function )
callbacks.add( array )callbacks:另一个$.Callbacks对象,将其回调添加到当前列表。function:要添加的回调函数。array:包含多个回调函数的数组。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks add 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="addBtn">添加多个回调</button>
<button id="fireBtn">触发</button>
<div id="display"></div>
<script>
var callbacks = $.Callbacks();
function fn1() { $('#display').append('<p>fn1</p>'); }
function fn2() { $('#display').append('<p>fn2</p>'); }
$('#addBtn').on('click', function() {
callbacks.add([fn1, fn2]); // 使用数组添加
});
$('#fireBtn').on('click', function() {
callbacks.fire();
});
</script>
</body>
</html>remove()
语法
callbacks.remove( function )function:要从列表中移除的回调函数。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks remove 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="addBtn">添加回调</button>
<button id="removeBtn">移除回调</button>
<button id="fireBtn">触发</button>
<div id="out"></div>
<script>
var callbacks = $.Callbacks();
var fn = function() { $('#out').append('<p>回调执行</p>'); };
$('#addBtn').on('click', function() {
callbacks.add(fn);
});
$('#removeBtn').on('click', function() {
callbacks.remove(fn);
});
$('#fireBtn').on('click', function() {
callbacks.fire();
});
</script>
</body>
</html>fire()
语法
callbacks.fire( arguments )arguments:传递给回调函数的参数。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks fire 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fireArgsBtn">传递参数触发</button>
<div id="log"></div>
<script>
var callbacks = $.Callbacks();
callbacks.add(function(a, b) {
$('#log').append('<p>和: ' + (a + b) + '</p>');
});
$('#fireArgsBtn').on('click', function() {
callbacks.fire(5, 3);
});
</script>
</body>
</html>fireWith()
语法
callbacks.fireWith( context [, arguments] )context:回调函数内部的this指向。arguments:传递给回调函数的参数数组。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks fireWith 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fireWithBtn">触发指定上下文</button>
<div id="display"></div>
<script>
var callbacks = $.Callbacks();
var obj = { name: '上下文对象' };
callbacks.add(function() {
$('#display').append('<p>this.name: ' + this.name + '</p>');
});
$('#fireWithBtn').on('click', function() {
callbacks.fireWith(obj, ['额外参数']); // 参数可传可不传
});
</script>
</body>
</html>disable()
语法
callbacks.disable()禁用回调列表。此后任何添加、移除、触发等操作都将无效。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks disable 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="disableBtn">禁用列表</button>
<button id="fireBtn">触发</button>
<div id="status"></div>
<script>
var callbacks = $.Callbacks();
callbacks.add(function() {
$('#status').append('<p>回调触发</p>');
});
$('#disableBtn').on('click', function() {
callbacks.disable();
$('#status').append('<p>列表已禁用</p>');
});
$('#fireBtn').on('click', function() {
callbacks.fire();
});
</script>
</body>
</html>disabled()
语法
var isDisabled = callbacks.disabled()返回一个布尔值,表示回调列表是否已被禁用。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks disabled 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="checkBtn">检查状态</button>
<button id="disableBtn">禁用列表</button>
<div id="info"></div>
<script>
var callbacks = $.Callbacks();
$('#checkBtn').on('click', function() {
$('#info').text('列表是否禁用: ' + callbacks.disabled());
});
$('#disableBtn').on('click', function() {
callbacks.disable();
});
</script>
</body>
</html>lock()
语法
callbacks.lock()锁定回调列表的当前状态。已触发的列表无法再次触发(除非有 memory 标志)。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks lock 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="lockBtn">锁定列表</button>
<button id="fireBtn">触发</button>
<div id="msg"></div>
<script>
var callbacks = $.Callbacks('memory');
callbacks.add(function() {
$('#msg').append('<p>回调执行</p>');
});
$('#lockBtn').on('click', function() {
callbacks.lock();
});
$('#fireBtn').on('click', function() {
callbacks.fire();
});
</script>
</body>
</html>locked()
语法
var isLocked = callbacks.locked()返回一个布尔值,表示回调列表是否已被锁定。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks locked 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="checkLocked">检查锁定状态</button>
<button id="lockBtn">锁定</button>
<div id="result"></div>
<script>
var callbacks = $.Callbacks();
$('#checkLocked').on('click', function() {
$('#result').text('是否锁定: ' + callbacks.locked());
});
$('#lockBtn').on('click', function() {
callbacks.lock();
});
</script>
</body>
</html>empty()
语法
callbacks.empty()清空回调列表中的所有函数。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks empty 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="addBtn">添加回调</button>
<button id="emptyBtn">清空列表</button>
<button id="fireBtn">触发</button>
<div id="log"></div>
<script>
var callbacks = $.Callbacks();
var fn = function() { $('#log').append('<p>回调</p>'); };
$('#addBtn').on('click', function() {
callbacks.add(fn);
});
$('#emptyBtn').on('click', function() {
callbacks.empty();
});
$('#fireBtn').on('click', function() {
callbacks.fire();
});
</script>
</body>
</html>has()
语法
callbacks.has( function )返回一个布尔值,表示指定的回调函数是否存在于列表中。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$.Callbacks has 方法示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="checkBtn">检查是否存在</button>
<div id="info"></div>
<script>
var callbacks = $.Callbacks();
var fn1 = function() {};
var fn2 = function() {};
callbacks.add(fn1);
$('#checkBtn').on('click', function() {
var hasFn1 = callbacks.has(fn1);
var hasFn2 = callbacks.has(fn2);
$('#info').html('fn1 存在: ' + hasFn1 + '<br>fn2 存在: ' + hasFn2);
});
</script>
</body>
</html>实际应用场景
示例:观察者模式实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>观察者模式示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="updateBtn">发布更新</button>
<button id="subscribe1">订阅者1</button>
<button id="subscribe2">订阅者2</button>
<div id="output"></div>
<script>
var publisher = {
callbacks: $.Callbacks(),
publish: function(data) {
this.callbacks.fire(data);
},
subscribe: function(fn) {
this.callbacks.add(fn);
},
unsubscribe: function(fn) {
this.callbacks.remove(fn);
}
};
var subscriber1 = function(data) {
$('#output').append('<p>订阅者1收到: ' + data + '</p>');
};
var subscriber2 = function(data) {
$('#output').append('<p>订阅者2收到: ' + data + '</p>');
};
$('#subscribe1').on('click', function() {
publisher.subscribe(subscriber1);
});
$('#subscribe2').on('click', function() {
publisher.subscribe(subscriber2);
});
$('#updateBtn').on('click', function() {
publisher.publish('新数据 ' + new Date().toLocaleTimeString());
});
</script>
</body>
</html>版本变更记录
| 版本 | 变更说明 |
|---|---|
| 1.7 | 引入 jQuery.Callbacks() 对象,提供统一的多用途回调列表管理功能。 |
| 1.8 | 增强 memory 标志的行为,使其在列表被锁定后仍能正常工作。 |
| 1.11 | 修复了与 stopOnFalse 相关的某些边界情况下的行为不一致问题。 |
| 3.0 | 优化了内部实现,提高了性能和内存效率。$.Callbacks 的 API 保持不变。 |
| 4.0 | 从“slim”构建版本中移除了 $.Callbacks 和 $.Deferred 模块,以减小体积。但完整构建版本中依然保留,功能不变。若需要 IE11 支持,应使用完整构建版本。 |
浏览器兼容性
基于 jQuery 3.x 或 4.x 版本,$.Callbacks() 的兼容性与 jQuery 核心库一致。对于 jQuery 4.x,已移除对 IE 10 及以下版本的支持。
| 浏览器类型 | 最低兼容版本(基于 jQuery 3.x/4.x) |
|---|---|
| PC 端 | |
| Chrome | 60+ (当前及先前主要版本) |
| Edge | 15+ (基于 Chromium) |
| Firefox | 55+ (当前及先前主要版本) |
| Opera | 47+ (当前及先前主要版本) |
| Safari | 10+ (当前及先前主要版本) |
| 移动端 | |
| Chrome Android | 100+ (当前版本) |
| Firefox for Android | 100+ (当前版本) |
| Opera Android | 64+ (当前版本) |
| Safari on iOS | 10+ |
| Samsung Internet | 6.2+ |
| WebView Android | 100+ (当前版本) |
| WebView on iOS | 10+ |
掌握 $.Callbacks() 这一 jQuery回调函数 管理工具,能够极大地增强代码的灵活性和可维护性。无论是构建自定义事件系统,还是作为更复杂异步流程的基石,$.Callbacks() 都提供了一套简洁而强大的解决方案。通过合理运用不同的标志位和方法,可以精确控制回调函数的执行流程,满足多样化的编程需求。
