使用setTimeout丢失上下文,背景切换脚本setTimeout失效求助
Hey there! Let's break down what's going wrong with your script and fix that setTimeout issue step by step.
First: Fix the Initialization Bug
Your current code has a critical mistake in how you're setting up the init function:
$(document).ready(function() { window.onload = Main.init(); });
When you add () to Main.init, you're immediately running the function instead of assigning it as the window.onload handler. Plus, using both $(document).ready() and window.onload is redundant here—jQuery's ready fires as soon as the DOM is ready (which is all you need for a button click handler). Let's simplify that:
$(document).ready(function() { Main.init(); }); // Or even more concise: // $(document).ready(Main.init);
The Big Issue: this Binding in setTimeout
The main reason your setTimeout isn't working is almost certainly a this scope problem. Inside the each loop, when you pass a regular function to setTimeout, this will point to the global window object instead of the <div> element you're trying to target.
Here's a complete, fixed version of your script (I filled in the missing parts of your chBackground function):
var Main = { init: function() { // Bind `this` so `chBackground` has access to the Main object if needed $('#button').click(this.chBackground.bind(this)); }, chBackground: function() { $('#r1 > div').each(function(index) { // Store the current div in a variable to preserve its reference const $currentDiv = $(this); // Switch to your custom background $currentDiv.css('backgroundColor', '#ff4444'); // Replace with your custom color // Set timeout to revert to default—stagger timing with index if desired setTimeout(function() { $currentDiv.css('backgroundColor', '#ffffff'); // Replace with your default color }, 1000 * index); // Adjust delay; multiplying by index makes each div revert one after another }); } };
Why This Works
- We save the current
<div>to a$currentDivvariable inside theeachloop. This creates a closure that keeps the reference to the specific div alive whensetTimeoutruns later. - If you prefer modern JS, you could use an arrow function in
setTimeoutinstead—arrow functions inherit thethisvalue from their surrounding scope, so$(this)would still point to the current div:setTimeout(() => { $(this).css('backgroundColor', '#ffffff'); }, 1000 * index);
Pro Tip: Use CSS Classes Instead of Inline Styles
For cleaner, more maintainable code, avoid hardcoding colors in JavaScript. Define CSS classes instead:
.default-bg { background-color: #ffffff; } .highlight-bg { background-color: #ff4444; }
Then update your script to use class toggles:
$currentDiv.addClass('highlight-bg'); setTimeout(() => { $currentDiv.removeClass('highlight-bg').addClass('default-bg'); }, 1000 * index);
内容的提问来源于stack exchange,提问作者linearSpin

