闭包案例---每隔一秒打印一个数

本文介绍了使用JavaScript的闭包和setTimeout函数实现定时打印递增数字的方法。通过两种不同的闭包方式,确保了每次调用都能正确打印当前循环变量的值,避免了常见的时间函数陷阱。
// 每个一秒打印一个数
    // 方法一:利用闭包实现
    for (var i = 1; i <= 5; i++) {
      (function (i) {
        setTimeout(() => {
          console.log(i);
        }, 1000 * i);
      })(i);
    }


    // 方法二:
    for (var i = 1; i <= 5; i++) {
      setTimeout((function (i) {
        return () => {
          console.log(i);
        }
      })(i), 1000 * i);
    }

 

转载于:https://www.cnblogs.com/lixiaoxue/p/11228667.html

<think>我们有一个明确的需求:实现每隔一秒打印一次字(例如1,2,3,...)。根据引用内容,有多种方法可以实现这个需求。下面我将总结几种常见的方法,包括JavaScript(ES5和ES6)和Python,以及C语言(使用setitimer)。同时,我会提供代码示例并解释原理。 ## 方法一:JavaScript(使用setTimeout) ### ES6版本(使用let块级作用域) 在ES6中,可以使用`let`关键字声明循环变量,因为`let`具有块级作用域,每次循环都会创建一个新的变量绑定。这样,每个定时器回调函数捕获的都是当前循环的变量值。 ```javascript for (let i = 1; i <= 10; i++) { setTimeout(function () { console.log(i); }, 1000 * i); } ``` **解释**: - 循环从110,每次设置一个定时器。 - 每个定时器的时间间隔为`1000 * i`毫,即第1个在1打印,第2个在2打印,以此类推。 - 由于使用`let`,每个`i`都是独立的,因此打印的值分别是1,2,...,10。 ### ES5版本(使用闭包) 在ES5中,由于`var`没有块级作用域,我们需要使用立即执行函数表达式(IIFE)为每次循环创建一个闭包,以捕获当前的`i`值。 ```javascript for (var i = 1; i <= 10; i++) { (function (j) { setTimeout(function () { console.log(j); }, 1000 * j); })(i); } ``` **解释**: - 在每次循环中,我们将当前的`i`作为参`j`传递给立即执行函数- 由于函数是按值传递的,每个立即执行函数内部的`j`都是独立的,因此定时器回调函数打印的是正确的`j`值。 ## 方法二:Python(使用time.sleep) 在Python中,我们可以使用一个循环,每次打印后休眠一秒。 ```python import time n = 1 while n <= 10: # 这里以10为例,可以修改为任意字 print(n) n += 1 time.sleep(1) # 暂停1 ``` **解释**: - 初始化变量`n`为1- 进入循环,打印`n`,然后将`n`加1- 使用`time.sleep(1)`让程序暂停1- 循环继续直到`n`超过10。 ## 方法三:C语言(使用setitimer) 在C语言中,可以使用`setitimer`函数设置一个间隔定时器,并在信号处理函数打印字。注意,由于信号处理函数的限制,我们通常只能使用异步信号安全的函数(如`write`),但这里为了简单使用`printf`(在Linux下通常可以工作,但严格来说不是异步信号安全的)。 ```c #include <stdio.h> #include <sys/time.h> #include <signal.h> #include <unistd.h> int count = 1; // 全局计器 void print_hello(int signum) { printf("%d\n", count++); fflush(stdout); // 立即刷新输出缓冲区 if (count > 10) { // 达到10次后停止定时器 struct itimerval timer; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 0; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &timer, NULL); } } int main() { struct itimerval timer; // 设置第一次触发时间为1后 timer.it_value.tv_sec = 1; timer.it_value.tv_usec = 0; // 设置间隔时间为1 timer.it_interval.tv_sec = 1; timer.it_interval.tv_usec = 0; // 注册信号处理函数 signal(SIGALRM, print_hello); // 启动定时器 setitimer(ITIMER_REAL, &timer, NULL); // 主循环,等待定时器信号 while (count <= 10) { pause(); // 暂停等待信号 } return 0; } ``` **解释**: - 使用全局变量`count`记录当前要打印字。 - 设置定时器,第一次在1后触发,之后每隔1触发一次,发送`SIGALRM`信号。 - 信号处理函数`print_hello`打印当前的`count`,然后自增。当打印10时,取消定时器(通过设置定时器间隔为0)。 -函数中通过`pause()`等待信号。 ## 总结 以上方法分别在不同的编程语言中实现每隔一秒打印一个字的功能: 1. **JavaScript**:利用`setTimeout`和闭包(或块级作用域)实现异步定时打印。 2. **Python**:使用循环和`time.sleep`实现同步等待。 3. **C语言**:使用`setitimer`设置定时器,通过信号处理函数实现。 你可以根据自己的编程环境选择合适的实现方式。 --- ### 相关问题 1. JavaScript中除了使用`setTimeout`,还有其他方法实现定时任务吗? 2. 在Python中如何实现非阻塞的定时任务? 3. C语言中定时器信号处理函数有哪些注意事项? [^1]: 引用内容1 [^2]: 引用内容2 [^3]: 引用内容3 [^4]: 引用内容4 [^5]: 引用内容5 </think> 下面我将详细解释如何实现每隔一秒打印一次字(如打印1,2,3...),并提供多种编程语言的实现方案: ### 一、核心原理 使用定时器机制控制输出间隔: 1. 初始化计器(如 `let i = 0`) 2. 设置重复触发的定时器 3. 每次触发时执行: - 打印当前-器+1 - 达到上限时清除定时器 ### 二、JavaScript实现方案 #### 1. ES6方案(推荐) ```javascript let i = 1; const timer = setInterval(() => { console.log(i); if (i++ >= 5) clearInterval(timer); // 打印到5停止 }, 1000); ``` #### 2. ES5方案(闭包) ```javascript for (var i = 1; i <= 5; i++) { (function(j) { setTimeout(() => console.log(j), 1000 * j); })(i); } ``` #### 3. 使用async/await ```javascript const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); async function printNumbers() { for (let i = 1; i <= 5; i++) { await delay(1000); console.log(i); } } printNumbers(); ``` ### 三、Python实现方案 #### 1. 基础循环 ```python import time for i in range(1, 6): print(i) time.sleep(1) # 暂停1 ``` #### 2. 定时器回调 ```python import threading def print_num(n): print(n) if n < 5: threading.Timer(1, print_num, [n+1]).start() print_num(1) ``` ### 四、C语言实现(UNIX系统) ```c #include <stdio.h> #include <unistd.h> // sleep() int main() { for (int i = 1; i <= 5; i++) { printf("%d\n", i); fflush(stdout); // 立即刷新输出缓冲区 sleep(1); // 等待1 } return 0; } ``` ### 五、关键区别对比 | 方法 | 特点 | 适用场景 | |---------------|-----------------------------|--------------------| | setInterval | 固定间隔重复执行 | JS持续定时任务 | | setTimeout | 精确控制每次延迟 | JS单次/链式定时任务 | | time.sleep | 同步阻塞 | Python简单脚本 | | threading.Timer| 异步非阻塞 | Python复杂定时任务 | > **注意**:浏览器环境中建议使用 `requestAnimationFrame` 实现动画计时,Node.js 环境可用 `setImmediate` 优化性能[^1][^5]。 ### 六、常见问题解决 **问题:输出延迟累积** ```javascript // 解决方案:基于准确时间计算 let start = Date.now(); let count = 0; function printAccurate() { count++; const elapsed = Date.now() - start; console.log(`精确计: ${count} 耗时: ${elapsed}ms`); if (count < 5) { const nextTime = 1000 * count - elapsed; setTimeout(printAccurate, Math.max(0, nextTime)); } } printAccurate(); ``` --- ### 相关问题 1. 如何在浏览器中实现精确的动画帧计时? 2. JavaScript 的 `setTimeout` 和 `setInterval` 有哪些性能差异? 3. 如何用 Python 的 asyncio 实现非阻塞定时任务? : 引用内容1 : 引用内容2 : 引用内容3 : 引用内容4 [^5]: 引用内容5
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值