zoukankan      html  css  js  c++  java
  • [Effective JavaScript 笔记] 第12条:理解变量声明提升

    js支持词法作用域,即除了极少的例外,对变量的引用会被绑定到声明变量最近的作用域中。

    js不支持块级作用域,即变量定义的作用域并不是离其最近的封闭语句或代码块,而是包含它们的函数。

    不了解这个会产生一些微妙的bug。

    functon isWinner(palyer,others){
    
              var highest=0;
    
             for(var i=0,n=others.length;i<n;i++){
    
                       var palyer=others[i];
    
                      if(player.score>highest){
    
                               highest=player.score;
    
                      }
    
            }
    
             return player.score>highest;
    
    }
    

      

    这里的for循环里声明了一个局部变量player,但由于js中变量是函数级作用域,而不是块级作用域,所以在内部声明的player变量只是简单地重声明了一个已经存在于作用域内的变量(参数player)

    该循环每次迭代都会重写同一变量。因此return 语句将player看作others的最后一个元素,而不是此函数的参数player。

    理解js变量声明行为的一个好方法,是把变量声明看作两个过程,一个是声明过程,一个是赋值过程

    js隐式提升的是声明部分到封闭函数的顶部,而将赋值留在原地。所以上面的函数相当于。

    functon isWinner(palyer,others){
    
              var highest=0;
    
              var palyer;
    
             for(var i=0,n=others.length;i<n;i++){
    
                    palyer=others[i];
    
                    if(player.score>highest){
    
                         highest=player.score;
    
                     }
    
             }
    
            return player.score>highest;
    
    }
    

      

    在同一函数中多次声明相同变量是合法的。变量声明提升也可能导致变量重声明的混淆。

    function trimSections(header,body,footer){
    
           for(var i=0,n=header.length;i<n;i++){
    
                       header[i]=header[i].trim();
    
           }
    
          for(var i=0,n=body.length;i<n;i++){
    
               body[i]=body[i].trim();
    
           }
    
          for(var i=0,n=footer.length;i<n;i++){
    
                    footer[i]=footer[i].trim();
    
          }
    
    }
    

      

    经过变量提升后相当于

    for(i=0,n=body.length;i<n;i++){
    
           body[i]=body[i].trim();
    
    }
    
    for(i=0,n=footer.length;i<n;i++){
    
           footer[i]=footer[i].trim();
    
    }
    

      

    因为重声明会导致截然不同的变量展现,一些程序员喜欢通过有效地手动提升变量将所有的var声明放置在函数的顶部,从而避免歧义。

    重要的是,不管是写代码还是读代码,都要理解js的作用域规则

    js 没有块级作用域的一个例外好处是其异常处理。

    try…catch语句将捕获的异常绑定到一个变量,该变量的作用域只是catch块。

    function test(){
    
            var x=”var”,res=[];
    
            res.push(x);
    
            try{
    
                   throw “exception”;
    
            }catch(x){
    
                x=”catch”;
    
           }
    
           res.push(x);
    
           return res;
    
    }
    
    test();//[”var ”,”var ”]
    

      

    提示

    • 在代码块中的变量声明会被隐式地提升到封闭函数的顶部
    • 重声明变量被视为单个变量
    • 考虑手动提升局部变量的声明,从而避免混淆
  • 相关阅读:
    跟随标准与Webkit源码探究DOM -- 获取元素之querySelector,querySelectorAll
    跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByClassName
    跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByTagName
    跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByName
    跟随标准与Webkit源码探究DOM -- 获取元素之getElementById
    原生DOM探究 -- NodeList v.s. HTMLCollection
    Jira 在流程节点中每个状态权限设置
    Eureka集群配置
    Linux下搭建 redis
    python框架django中结合vue进行前后端分离
  • 原文地址:https://www.cnblogs.com/wengxuesong/p/5499087.html
Copyright © 2011-2022 走看看