• javascript作用域中令你意想不到的问题


    大多数类c的语言,由一对花括号封闭的代码块就是一个作用域。但是javascript的作用域则是通过函数来定义。在一个函数中定义的变量只对这个函数内部可见,我们称为函数作用域。

    1.在函数中引用一个变量,javascript会先搜索当前函数作用域,没有找到则搜索上层作用域,一直到全局作用域。

    var a = 123;
    var f = function(){
      console.log(a);
      var a = 456;
    }
    f() 
    你可能预想会输出123,但实际上输出的undefined。why?我们可以通过上述的文字描述进行分析,调用f函数,在console.log访问a变量时,javascript会先搜索当前函数作用域,恰巧在f函数作用
    域内搜索到a变量,所以外层变量设置的a=123就会被屏蔽掉,但是执行到console.log时,a还未被初始化,所以输出为未定义。
    我们可以进一步理解为无论在函数内部任何地方定义的变量(即不分先后顺序),在一进入函数时就被定义,但直到运行到var那一行,才初始化值。

    2.函数作用域的嵌套关系

    函数作用域的嵌套关系是定义时决定的,而不是调用时决定的。也就是说javascript的作用域是静态作用域,作用域的嵌套关系在语法分析时确定,而不必等到运行时确定。如何理解呢?看下边的例子。

    var a = 123;
    var f1 =function(){
      console.log(a)
    };
    var f2 =function(){
       var a = 456 ;
       f1();
    };
    f2();
    你可能预想会输出456,然而再次事与愿违,实际输出的是123.通过f2调用的f1,在查找a的定义时,找到的是f1父作用域定义的a变量(即全局作用域的a变量),而不是f2中定义的a变量。
    说明函数作用域的嵌套关系是在定义时决定的,而不是调用时才确定。
    var a = [1,2,3]
    for(var i = 0;i < a.length ;i++){
        setTimeout(function(){
         console.log(a[i]) },
    100) }
    //三次输出都是未定义。因为setTimeout相当于异步操作,那么在循环结束之后,i变量值为3.然后当0.1秒后,console.log调用i,三次输出的i的值都为3,a[3]自然就不存在

    按照下边设置,就可以按照正常输出1,2,3,相当于建立了闭包,传入的i在setTimeout函数没有执行完不会销毁。

    var a = [1,2,3]
    for(var i = 0;i < a.length ;i++){
    (function(i){setTimeout(function(){
         console.log(a[i])
    },100)})(i)
    }

     
  • 相关阅读:
    Eclipse之注释操作
    Eclipse之查找、替换操作
    思维游戏(4)之有问题的楼房
    第七层 应用层
    第三章 进程
    第一章 导论
    软件开发流程
    单元测试
    Google Chrome浏览器调试
    python安装完毕后,提示找不到ssl模块的解决步骤
  • 原文地址:https://www.cnblogs.com/dupd/p/6105846.html
Copyright © 2020-2023  润新知