首页 > 试题广场 >

控制台打印的结果是?

[单选题]
for(let i=0;i<2;i++){
    setTimeout(function(){
    console.log(i)
    },100);
}
for(var i=0;i<2;i++){
    setTimeout(function(){
        console.log(i)
    },100);
}
问:控制台打印的结果是?

  • 0 1 2 2
  • 0 1 0 1
  • 0 1 1 1
  • 1 1 0 0
第一个:let将i绑定到for循环快中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的function()属于一个新的域,通过 var 定义的变量是无法传入到这个函数执行域中的,通过使用 let 来声明块变量,这时候变量就能作用于这个块,所以 function就能使用 i 这个变量了;输出为0,1.
第二个:settimeout是异步执行,1s后往异步任务队列里面添加一个任务,只有同步的全部执行完,才会执行异步任务队列里的任务,当主线执行完成后,i是2,所以此时再去执行任务队列里的任务时,所以输出两次2.
编辑于 2019-07-01 21:31:35 回复(4)
更多回答
①Js是单线程的,Settimeout是异步宏任务,所以代码执行遇到异步的,就放在事件队列中的,等线程中的任务执行完后才会执行事件队列中的任务。② let是es6中声明变量的方式,有自己的作用域块,可以放变量,所以let绑定for循环时,每个i都有自己的值. 在这个for循环中就是满足一次条件向事件队列中添加一个打印i的事件,且每个事件中的i有自己的值 ③Var没有作用域块,for循环的变量就会后一个覆盖前一个,当循环完毕时i就只有一个值,又因为for循环的判断条件是不满足跳出,所以i最后是2而不是1 ④这些完了后执行事件队列中的任务,就打印了0122
编辑于 2019-10-13 17:26:13 回复(11)
他们的解释有点复杂,我看了好几个才看明白,总的来说就是,js是单线程,所以等待输出了等一个函数才开始第二个,所以是0 1,然后第二个函数由于定时函数生效,然而for循环是一瞬间完成的,所以for循环已经走完了,然而延时函数才准备输出,此时i为2,所以输出了两次i=2
发表于 2021-01-12 17:49:25 回复(4)

let作用域for循环时会绑定i状态值,所以定时器触发后,分别输出的是0,1两个值。var变量for循环时不会绑定i状态值,当i=1时,i<2成立,此时i++,i的值变成2,所以定时器触发后,分别输出的是2,2。

发表于 2019-06-30 11:12:45 回复(1)
第二个形成了闭包,for循环执行后i为2,当定时器回调函数执行是i就为2了; let存在变量提升,但不存在初始化,因此生成暂时性死区,不存在闭包,所以两次执行结果为0,1
发表于 2019-11-04 11:44:37 回复(14)
1.settimeout会延迟执行,所以两个循环体都会延迟执行两次2.两个循环体会先循环完,最终的i都为23.let i只对每一次循环有效,因为是有对局部作用域内有效。var i 是全局的,所以最后打印为0122
发表于 2021-06-19 18:52:03 回复(0)
<p>Var定义的变量没有块级作用域,所以异部执行的时候for先全部运行结束再进行异部操作</p>
发表于 2020-12-01 21:35:17 回复(0)
主要说一下第二个for循环,var定义的 i 是全局变量,因为 setTImeout()是异步执行的,也就是说:
for(var i=0;i<2;i++){
setTimeout(function(){
console.log(i)
},100
);
}
上面这段代码,可以这么理解
for(var i=0;i<2;i++){
//这里当 i = 2的时候,跳出循环,因为用var定义,是全局变量( i = 2)
}
setTimeout(function(){
//根据全局变量,此时 i = 2 ; 因为for循环有两次,所以打印两次2 ,
console.log(i)
},100
);

打印两次的原因,可以这样理解
for(var i=0;i<2;i++){ 
//同步的循环执行完后,得到 i = 2 , 然后再执行异步的循环
setTimeout(function(){
      i = 2 ; // 拿到全局声明变量 i = 2 ;
      // 异步函数第一次执行循环,得到全局变量 i 的值为 2 
      // 异步函数第二次执行循环,得到全局变量 i 的值也为 2 
      console.log(i)
},100
);
}
所以:最终结果为:0    1    2    2





编辑于 2019-08-02 14:28:23 回复(4)

这个题有问题🤨第二个题应该是输出1,1吧


发表于 2019-06-30 09:10:09 回复(5)

循环结束的时候i=2, settionmout执行conso.log(i)


发表于 2019-08-02 01:49:44 回复(2)
扫了一眼没找到答案2222 ,于是瞎蒙一个对了。 过来看解析才发现第一个i是let声明……
发表于 2022-08-13 15:52:28 回复(1)
总的来说就是let定义的i无论循环多少次,下一次再执行循环的时候,i仍然为0;但是var定义的i在下一次循环的时候会变为1覆盖掉之前的0,所以执行延时函数的时候输出为0,1;最后,由于是延时输出的,这个时候循环已经完成了,而由于var覆盖原则,i=2,最后执行函数输出为两个2.
发表于 2021-07-28 12:00:18 回复(0)
在es5只有全局作用域和函数作用域,es6引进了块级作用域。let,const会产生块级作用域。循环的每一次执行都会过得到let变量的值,但是var申明变量是全局的,异步任务执行时单线程中的for循环已经执行完了,i已经变为2。 补充一点let不会发生变量提升
发表于 2019-12-18 10:13:55 回复(0)
第二个setTimeout里应该是一个传入参数的立即执行函数,每100ms执行一次,结果就会输出0,1。修改如下
for(var i=0;i<2;i++){
  setTimeout(function(i){
     console.log(i)
  }(i),100);
}

发表于 2019-06-05 18:19:03 回复(0)
let 有块级作用域,所以输出的for循环分别输出三个不同的i(即是012),var 无块级作用域,所以i 在for循环会受到影响,最终i等于2.
setTimeout虽然是异步宏任务,用let 定义时 变量是三个不同的i。  用var 定义时 i 相互覆盖.
发表于 2022-09-24 21:16:49 回复(0)
每次遍历都会生成一个定时器,一共就四个,这些定时器会放到栈里面,然后for执行完了在把定时器放到js里面 ,顺序是先拿出var定义的~再拿出let定义的,因为栈先进后出,因为let在前就先运行了,运行以后i就是2了,然后var的值被let覆盖了,因为都是i,所以var的那个就只打印2了
编辑于 2022-06-16 13:34:52 回复(0)
         setTimeout()函数回调属于异步任务,会出现在宏任务队列中,
         被压到了任务队列的最后,在这段代码应该是for循环这个同步任务执行完成后才会轮到它,
         所以for循环在遍历过程中i不断加1,直到i判断失败一次才停止,
         这时候i为2,也就是说空跑了2次循环。
         等到了setTimeOut预定的时间后就会执行在for遍历过程中声明的2个setTimeout。
         所以最终运行后会出现上面的结果

发表于 2022-03-21 13:22:50 回复(0)
简单说一下自己的看法,就是let定义的i每次执行都会初始化为0,而var定义的i是全局变量,会被之前let定义的覆盖为1,所以第一次执行函数输出为01,因为函数存在延迟执行,而且判断语句为i大于或等于2是循环停止,所以第二次输出的值为22(自己的理解,不清楚是否正确,仅供参考)
发表于 2021-11-18 13:44:38 回复(1)
这道题考的是块级作用域和全局作用域对于这个定时器的一个作用,因为这个js 是单线程的,所以在遇到这个定时器函数的时候,就会额外的开辟一个线程去执行这个定时器函数,而以上的i不同之处就是定义的关键字不同,let是定义一个块级作用域,正因为他是块级作用域,所以它每次打印的结果不同,而var声明的是一个全局作用域,也就是说,等到最后一次判定i为2时,挑出该循环,同时打印2
编辑于 2021-10-26 16:04:31 回复(3)
这题跟es6 页面打出来都是报错的 只要let 一出来准报错
发表于 2021-08-10 10:55:18 回复(0)