
本文解析为何点击捐赠/取消捐赠按钮时数字首次不更新,而颜色却立即变化——根本原因在于混淆了 i++(后置递增)与 ++i(前置递增)的执行时机与返回值。
在 JavaScript 中,i++ 和 ++i 虽然都使变量 i 增加 1,但返回值不同,这直接导致了你观察到的“两击才生效”的异常行为。
- i++(后置递增):先返回 i 的当前值,再执行 i = i + 1
- ++i(前置递增):先执行 i = i + 1,再返回更新后的值
来看原始代码的关键问题:
donate = function(){
donateButton.style.backgroundColor = 'red';
tracker.innerHTML = i++; // ❌ 错误:赋值的是旧值,i 在赋值后才加 1
}假设初始 i = 0:
- 第 1 次点击 → tracker.innerHTML = 0(显示 0),然后 i 变为 1;
- 第 2 次点击 → tracker.innerHTML = 1(显示 1),然后 i 变为 2;
→ 视觉上总是“慢一步”,造成“需两次点击才显示变化”的错觉。
同理,i-- 也会导致 tracker 显示旧值,而 --i 才能确保显示更新后的结果。
立即学习“Java免费学习笔记(深入)”;
✅ 正确写法应使用前置运算符,并增加基础防护逻辑(如避免负数):
const donateButton = document.getElementById("donate");
const unDonateButton = document.getElementById("undonate");
const tracker = document.getElementById("container");
let i = 0; // 推荐用 let 替代 var,避免变量提升隐患
tracker.textContent = i; // 使用 textContent 更安全(防 XSS),且语义更清晰
const donate = () => {
donateButton.style.backgroundColor = 'red';
tracker.textContent = ++i; // ✅ 先加 1,再赋值显示
};
const undonate = () => {
if (i > 0) { // 防止食物数量为负
unDonateButton.style.backgroundColor = 'blue';
tracker.textContent = --i; // ✅ 先减 1,再赋值显示
} else {
unDonateButton.style.backgroundColor = ''; // 可选:重置样式
alert('Cannot un-donate: no food available!');
}
};
donateButton.addEventListener("click", donate);
unDonateButton.addEventListener("click", undonate);? 额外优化建议:
- 使用 textContent 替代 innerHTML(除非需渲染 HTML),更安全、性能更好;
- 将 i 声明为 let(块级作用域),避免意外全局污染;
- 为 undonate 添加边界检查,提升用户体验与健壮性;
- 可进一步封装状态管理(如用对象保存 count 和 UI 同步逻辑),为后续扩展打基础。
掌握前置/后置递增递减的区别,不仅是修复此 Bug 的关键,更是理解 JavaScript 表达式求值顺序的重要一课。










