一道js面试题

for(var i=0; i<10; i++){
  setTimeout(function() {
    console.log(i);
  },0)
}

请问输出什么?
如果要输出'0123456789',要怎么改?

阅读 5.1k
12 个回答

上面各位说得很全面了,推荐将 var 替换为 let拥抱 es6 吧

for(let i=0; i<10; i++){
  setTimeout(function() {
    console.log(i);
  },0)
}

这里简单说明一下为什么如此替换会有效。

  1. var 命令声明的变量,在全局范围内有效。例中代码,全局只有一个变量 i。每一次循环,i 的值均会改变,而 console.log(i) 里面的 i 指向的就是全局的 i,导致运行时输出的是最后一轮的 i 的值,即 10
  2. let 命令声明的变量,仅在块级作用域内有效。修改后的代码,每一次循环的 i 都是一个新的变量,所以最后输出 0123456789

另外一点,如果每一轮循环的变量 i 均为重新声明,那它怎么知道上一轮循环的值?
因为记得。JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量 i 时,就在上一轮循环的基础上进行计算。

最简单的方法 var 改成let 这是es6的方式

没有es6的话 还是用原始的闭包吧
for (var i = 0; i < 10; i++) {

(function(j) {
    setTimeout(function timer() {
        console.log(j);
    }, 0);
})(i);

}

最简单的:
for (var i = 0;i < 10;i++) {
    console.log(i);
}

使用闭包:

const Greeters = []
for (let i = 0 ; i < 10 ; i++) {
  Greeters.push(function () { return console.log(i) })
}
Greeters[0]() // 0
Greeters[1]() // 1
Greeters[2]() // 2
for(let i=0; i<10; i++){
  setTimeout(function() {
    console.log(i);
  },0)
}
for(var i=0; i<10; i++){
  (function(i) {
    setTimeout(function() {
    console.log(i);
  },0)
  })(i)
  
}

用es6语法,或者加个iife传i进去

原来的只会输出10个10出来

for(var i=0; i<10; i++){
     setTimeout(function() {
       console.log(i);
     }(i),0)
   }

输出值为0123456789

新手上路,请多包涵

setTimeout(function () {

    for (var i=0;i<10;i++){
        console.log(i)
    }
},0)

这个会输出10个10,因为setTimeout是异步加载.等他执行的时候,i已经全部成为10了.
如果要保留这个的值的话,可以使用闭包传参的方式

for(var i=0; i<10; i++){
  // 调用闭包,保留i的值
  (function(i) {
    setTimeout(function() {
      console.log(i);
    },0)
  })(i); 
}

输出为10次10,

输出0123456789,可以试试这样

    var a = '';
    for(var i = 0; i < 10; i++){
       a += i;
    }
    console.log('a', a);
for(var i=0; i<10; i++){
  (function(i){
    setTimeout(function() {
      console.log(i);
    },0)
  })(i)
}

闭包,亲测可用

如果要输出'0123456789',要怎么改?

难道不是:

console.log('0123456789')

这样吗?

这是经典的闭包问题

for(var i=0; i<10; i++){
setTimeout(function() {

console.log(i);

},0)
}
这段代码 会输出10个10。
因为setTimeout会在for循环执行之后才运行。所以for循环相当于定义了10个函数:
function() {

console.log(i);

}

在for循环结束后,setTimeout触发,去运行之前的10个函数,这是i为10.
所以输出10个10.

要输出0123456789
1.使用let

  1. 不使用闭包

for (var i = 0;i < 10;i++) {

console.log(i);

}

  1. 使用闭包, 用匿名函数

for(var i=0; i<10; i++){
(function(i){

setTimeout(function() {
  console.log(i);
},0)

})(i)
}

这个是很经典的问题,建议楼主百度。这样了解的会比较深刻

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题