JavaScript函数作用域问题
PHP中文网
PHP中文网 2017-04-11 12:01:52
[JavaScript讨论组]
    var loop1, loop2, loop3, loop4, loop5;
    for (var i = 0; i <= 5; i++) {
        switch(i) {
            case 1:
                loop1 = function() { console.log(i++); };
                break;
            case 2:
                loop2 = function() { console.log(i++); };
                break;
            case 3:
                loop3 = function() { console.log(i++); };
                break;
            case 4:
                loop4 = function() { console.log(i++); };
                break;
            case 5:
                loop5 = function() { console.log(i++); };
                break;
            default:
                break;
        }
    }
    loop1();        //6
    loop2();        //7    
    loop3();        //8
    loop4();        //9
    loop5();        //10
    for (var i = 0; i <= 5; i++) {
        (function(i) {
            switch(i) {
                case 1:
                    loop1 = function() { console.log(i++); };
                    break;
                case 2:
                    loop2 = function() { console.log(i++); };
                    break;
                case 3:
                    loop3 = function() { console.log(i++); };
                    break;
                case 4:
                    loop4 = function() { console.log(i++); };
                    break;
                case 5:
                    loop5 = function() { console.log(i++); };
                    break;
                default:
                    break;
            }
        })(i);
    }
    loop1();        //1
    loop2();        //2
    loop3();        //3
    loop4();        //4
    loop5();        //5

关于函数的作用于问题,为什么会发生这种情况?

PHP中文网
PHP中文网

认证0级讲师

全部回复(3)
高洛峰

第一个是闭包,loop1,loop2,loop3,loop4,loop5中的变量引用的变量i其实是同一个,都是父function(这里应该是全局作用域)中的i。
注意:它们引用的是同一个变量,都是循环中的那个i。
所以当for循环结束的时候,i已经是6了;
所以调用loop1的时候,又因为输出的是i++(++在后,先引用,后加),即输出6,但i已经是7了;
后面依此类推,分别输出7,8,9,10.

第二个是匿名函数自执行,要注意跟第一个的区别。匿名函数自执行的方式可以看到,变量i以形参的形式传递到匿名函数内部了,所以在这个匿名函数中用到的i就不再是父function中的变量i了,完全是不同的两个。而且由于匿名函数自执行的原因,5个loop分别引用的也是各自的i,互不相关。
注意:它们引用的不再是同一个变量,不再是循环中的那个i
后面的就跟前面差不多了,不再解释

这个题目考的是闭包,可以查看闭包的相关资料。

大家讲道理

不能说这和函数作用域无关,闭包不就是基于函数作用域而来的嘛。
第一种形式如 @小石头若海 所说函数引用的i是全局作用域下的i而第二种形式确实把i传入一个匿名函数,这是函数里面的i不再是全局作用域下的i,而是当前匿名函数作用域的i了。所以结果不同。

伊谢尔伦

把第二种情况改写成这样

  for (var i = 0; i <= 5; i++) {
          (function(num) {
              switch(num) {
                  case 1:
                      loop1 = function() { console.log(num++); };
                      break;
                  case 2:
                      loop2 = function() { console.log(num++); };
                      break;
                  case 3:
                      loop3 = function() { console.log(num++); };
                      break;
                  case 4:
                      loop4 = function() { console.log(num++); };
                      break;
                  case 5:
                      loop5 = function() { console.log(num++); };
                      break;
                  default:
                      break;
              }
          })(i);
      }

你是否就能理解?
ps:闭包和匿名函数即便是有经验的程序员也经常混用,闭包指的是有权访问另一个函数作用域变量的函数,这里的关键就在于作用域链,立即执行函数是解析到就执行的,而匿名函数只会分配一个指向该函数的指针。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号