zoukankan      html  css  js  c++  java
  • 便写高质量JavaSript的68个高效方法 >> 二章:变量作用域 >> 第12条:理解变量声明提升

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

    bug1: 重声明

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

       该程序在for循环体内声明了一个局部变量player。但是由于JavaScript中变量是函数级作用域(function-scoped),而不是块级作用域,所以在内部声明的player变量只是简单地重声明了一个已经存在于作用域内的变量(即参数player)。该循环的每次迭代都会重写同一变量。因此,return语句将player看作others的最后一个元素,而不是此函数最初的player参数。

    理解JavaScript变量声明行为的一个好办法是把变量声明看作由两部分组成,即声明

    JavaScript隐式地提升(hoists)声明部分到封闭函数的顶部,而将赋值;留在原地。换句话说,变量的作用域是整个函数,但仅在var语句出现的位置进行赋值。如图提供变量声明提升的可视化图。

         图    变量声明提升

    bug2:   变量声明也可能导致变量重声明的混淆。在同一函数中多次声明相同变量是合法的。这在多个循环时会经常出现。

    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();
    
      }
    
    }
    trimSections函数好像声明了6个局部变量(3个变量i,3个变量n),但经过变量声明提升后其实只声明了2个。
    换句话说,经过变量声明提升后,trimSections函数等同于下面这个重写的版本。
    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();
    }
    因为重声明会导致截然不同的变量展现,一些程序员喜欢通过有效地手动提升变量将所有的var声明放置在函数的顶部,从而避免歧义
    无论你是否喜欢这种风格,重要的是,不管是写代码还是读代码,都要理解JavaScript的作用域规则。

    例外:异常处理。try...catch语句将捕获的异常绑定到一个变量,该变量的作用域只是catch语句块。

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

    提示:

    • 在代码块中的变量声明会被隐式地提升到封闭函数的顶部。
    • 重声明变量被视为单个变量。
    • 考虑手动提升局部变量地声明,从而避免混淆。
  • 相关阅读:
    [LeetCode][JavaScript]Copy List with Random Pointer
    [LeetCode][JavaScript]Best Time to Buy and Sell Stock II
    [LeetCode][JavaScript]Best Time to Buy and Sell Stock
    [LeetCode][JavaScript]Populating Next Right Pointers in Each Node
    [LeetCode][JavaScript]Text Justification
    [LeetCode][JavaScript]LRU Cache
    用CRTP在C++中实现静态函数的多态
    C++的静态分发(CRTP)和动态分发(虚函数多态)的比较
    用Y分钟学会X
    看看你能认出多少种编程语言
  • 原文地址:https://www.cnblogs.com/meiyanstar/p/13131649.html
Copyright © 2011-2022 走看看