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

JavaScript含setTimeout的test函数输出差异是否由闭包导致?

问题代码
function test(str) {
  setTimeout(() => {
    console.log(str);
  }, 10000);
}

let i = "1";
test(i); //test 1
console.log(i, "sync");

i = "2";
test(i); //test 2
console.log(i, "sync");

问题1:test 1、test 2依次打印1和2是不是闭包导致的?

不是,核心原因是JS基本类型的值传递特性:

  • 字符串属于JS基本数据类型,调用test(i)时,会把当前i的值完整拷贝一份赋值给test的形参str。两次调用test会生成两个独立的函数执行上下文,各自上下文里的str分别存储"1"和"2",互不干扰。
  • setTimeout的箭头函数确实形成了闭包,作用是让异步回调可以访问到当前test上下文里的str变量,但闭包不是输出差异的核心原因,核心是传参时已经做了值拷贝。

问题2:两种输出差异的原因

你描述的「去掉setTimeout直接打印str得到i最后取值」的场景,和原代码的差异本质是是否做了值拷贝、以及是否是异步执行:
首先要纠正一个误区:如果仅删除原代码里的setTimeout,直接打印形参str,运行结果是依次输出1、1 sync、2、2 sync,不会出现只输出i最后取值的情况。
你说的输出最后取值的场景,应该是test不接收参数,直接引用外部变量i的写法:

// 会输出两次2的写法
function test() {
  setTimeout(() => {
    console.log(i); // 直接引用外部的i,没有传参拷贝步骤
  }, 10000);
}

这种场景和原代码的差异原因:

  • 原代码传参时做了值拷贝,每个回调捕获的是各自上下文里独立的str,不管同步还是异步执行,拿到的都是调用时拷贝的值
  • 直接引用外部i的写法,所有回调捕获的是同一个作用域下的同一个i变量,异步回调执行时i已经被重新赋值为2,所以都会打印最后取值

内容的提问来源于stack exchange,提问作者Ali Özgenç

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:54:07