sunshine
管理员
管理员
  • 最后登录2023-10-30
  • 发帖数170
  • 社区居民
阅读:6748回复:0

[js]面试题 — 关于作用域的一道面试题

楼主#
更多 发布于:2018-04-25 10:21
题目如下:
<script>
    for(var i=0;i<5;i++){
           setTimeout(function(){
               console.log(i)
           },1000)
    }
    console.log(i);
</script>
上面代码的输出结果(请先思考 )?

   (请先思考 )?
   (请先思考 )?
   (请先思考 )?
 (请先思考 )?
结果为:先执行循环外的i , 输出结果5
             在输出setTimeOut里的i , 输出结果为5 个5


现在,请思考 ,如何可以输出5 ,   0,1,2,3,4
(请先思考 )?
(请先思考 )?
(请先思考 )?
(请先思考 )?

这时,大家想到了,可以用let , 代码如下:
<script>
    for(let i=0;i<5;i++){
           setTimeout(function(){
               console.log(i)
           },1000)
    }
    console.log(i);
</script>
for里的变量使用let , 根据let 的作用域, setTimeout的i ,可以分别输出0,1,2,3,4

但是,for外的i , 却不能访问到i , 而我们是想让它输出结果: 5

如何实现 ?
(请先思考 )?
(请先思考 )?
(请先思考 )?
(请先思考 )?

方法一 (直接使用简单的方法赋值,但是不够高级):
<script>
    for(var i=0;i<5;i++){
          let j = i;
           setTimeout(function(){
               console.log(j)
           },1000)
    }
    console.log(i);
</script>
解析:

      var声明的变量全局范围内都有效。所以每次循环,新的i值都会覆盖旧值
let声明的仅在块级作用域内有效,最后输出6
 let不会发生变量提升的现象,所以一定要在定义后使用,否则报错。
暂时性死区:只要块级作用域内存在let命令,它所声明的变量就绑定这个区域,不再受外部影响。
     详情参考:https://www.cnblogs.com/chengyunshen/p/7191571.html
方法二 (使用闭包,其实还是赋值,只是实参赋给形参)
<script>
    for(var i=0;i<5;i++){
        (function (j){
           setTimeout(function(){
               console.log(j)
           },1000)
       })(i);
    }
    console.log(i);
</script>

解析:
     闭包实现,其实主要也是因为函数,会创建自己对应的作用域,不会被改变

原创文章,转载请注明出处

http://bugshouji.com/shareweb/t454
游客


返回顶部

公众号

公众号