You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript循环中使用setTimeout延迟处理日期时结果异常的问题排查与解决

问题分析与解决方案

Hey there, let's break down why your code is spitting out the same date every time and fix it step by step!

问题根源

The core issue here is that JavaScript Date objects are reference types, not value types. Here's exactly what's happening in your code:

  1. You create one single date object at the start of the click handler.
  2. The for loop runs synchronously: it calls task(date, i) 10 times in quick succession, and immediately increments the same date object by 1 day each time—all before any of the setTimeout callbacks have a chance to run.
  3. By the time the first setTimeout callback fires (1 second later), the date object has already been bumped up 10 times to 2021-8-20. Since every task call holds a reference to this same object, all callbacks end up logging the final date.

修复方案

We need to pass a unique copy of the date object to each task call, so each callback uses the date state from that specific loop iteration. Here are two simple, reliable ways to do this:

方法1:每次循环创建Date副本

Modify your loop to pass a new Date instance (a copy of the current date) to task:

$('#loopDays').on('click', function(e){
    e.preventDefault();
    var numberOfDays = 10;
    let date = new Date($('#sDate').val()); 
    for (let i=0; i < numberOfDays; i++) { 
        // Create a copy of the current date for this iteration
        task(new Date(date), i); 
        date.setDate(date.getDate() + 1); 
    }

    function task(date, x){
        setTimeout(function() {
            // Optional: Add leading zeros for cleaner date formatting
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, '0');
            const day = String(date.getDate()).padStart(2, '0');
            console.log(`LOOP#${x}: ${year}-${month}-${day}`);
        }, 1000 * x); 
    }
});
  • new Date(date) creates a brand new Date object with the exact same value as the current date, so each task gets its own independent date that won't be altered by future loop iterations.

方法2:基于起始日期计算每轮日期

Alternatively, you can calculate the target date for each iteration upfront using the original start date, completely avoiding reference issues:

$('#loopDays').on('click', function(e){
    e.preventDefault();
    var numberOfDays = 10;
    let startDate = new Date($('#sDate').val()); 
    for (let i=0; i < numberOfDays; i++) { 
        // Calculate the date for this iteration directly from the start date
        const currentDate = new Date(startDate);
        currentDate.setDate(startDate.getDate() + i);
        task(currentDate, i); 
    }

    function task(date, x){
        setTimeout(function() {
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, '0');
            const day = String(date.getDate()).padStart(2, '0');
            console.log(`LOOP#${x}: ${year}-${month}-${day}`);
        }, 1000 * x); 
    }
});
  • This approach builds each iteration's date from the original start date, so you never modify the same object multiple times.

验证结果

After making either change, your output will match the expected逐日递增 dates:

LOOP#0: 2021-8-10
LOOP#1: 2021-8-11
LOOP#2: 2021-8-12
...
LOOP#9: 2021-8-19

内容的提问来源于stack exchange,提问作者Papilion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:14:09