便写高质量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"]
复制代码

提示:

  • 在代码块中的变量声明会被隐式地提升到封闭函数的顶部。
  • 重声明变量被视为单个变量。
  • 考虑手动提升局部变量地声明,从而避免混淆。

 

posted @   小那  阅读(191)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示