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 ”]

  

提示

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

[Effective JavaScript 笔记] 第12条:理解变量声明提升的更多相关文章

  1. [Effective JavaScript 笔记] 第9条:始终声明局部变量

    如果忘记将变量声明为局部变量,该变量将会隐式地转变为全局变量 function swap(a,i,j){ temp=a[i]; a[i]=a[j]; a[j]=temp; } 尽管该程序没有使用var ...

  2. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  3. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  4. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  5. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  6. [Effective JavaScript 笔记]第2章:变量作用域--个人总结

    前言 第二章主要讲解各种变量作用域,通过这章的学习,接触到了很多之前没有接触过的东西,比如不经常用到的eval,命名函数表达式,with语句块等,下面是一个列表,我对各节的一点点个人总结,很多都是自己 ...

  7. 解读JavaScript中的Hoisting机制(js变量声明提升机制)

    hoisting机制:javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 知识点一:javascript是没有 ...

  8. [Effective JavaScript 笔记] 第8条:尽量少用全局对象

    初学者容易使用全局变量的原因 创建全局变量毫不费力,不需要任何形式的声明(只要在非函数里用var 你就可以得到一个全局变量) 写得代码简单,不涉及到大的项目或配合(写hello world是不会有什么 ...

  9. [Effective JavaScript 笔记]第16条:避免使用eval创建局部变量

    js中的eval函数是一个强大.灵活的工具.强大的工具容易被滥用,所以了解是值得的.(本人只用过它来处理json数据).错误使用eval函数的方式一:允许它干扰作用域.调用eval函数会将其参数作为j ...

随机推荐

  1. unity3d 依赖关系获取预制件任意资源

    前段时间策划们想知道UI预制件中使用了哪些音效 N多预制件.N多音效!! 如果纯人工整理的话这还不累成狗? 累成狗不说,还容易出错 所以获取音频剪辑小工具就诞生了,将策划从死亡边缘拉了回来 我们先看一 ...

  2. EntityFramework中Mapper怎么定义联合主键?

    HasKey(m => new { m.StoreId, m.CarTypeId, m.CarLevel}) 用“new {}”联合主键以“,”分隔形式定义

  3. Android Studio之gradle的配置与介绍

    1.gradle的简单介绍 Gradle是可以用于Android开发的新一代的Build System,也是Android Studio默认的build工具.其实Gradle脚本是基于一种JVM语言- ...

  4. css为什么要用悬浮

    如果这个100px的宽度是一个Img,横内元素.右边也是横内元素的话和块级元素是不同的. 2.文字环绕图片. div下有个img然后有个span标签 img最好悬浮,悬浮虽然说脱离文档,但是还是占空间 ...

  5. AngularJS - 快速入门

    刚开始接触时总是去wiki或各种百科以了解一番. 它们会告诉我一些MVVM.双向数据绑定.依赖注入等等名词,觉得这些名词好上档次,然后我很可能就不打算用这个东西了. AngularJS是什么? 完全使 ...

  6. android常用的弹出提示框

    我们在平时做开发的时候,免不了会用到各种各样的对话框,相信有过其他平台开发经验的朋友都会知道,大部分的平台都只提供了几个最简单的实现,如果我们想实现自己特定需求的对话框,大家可能首先会想到,通过继承等 ...

  7. 在CentOS上装 ElasticSearch

    参考官方文档:Install Elasticsearch with RPM ElasticSearch依赖Java,所以需要先安装Java: 到Oracle官网找到下载链接 http://www.or ...

  8. Spring MVC设计模式

    MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器 使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式.比如一批统计数据可以分别用柱状图.饼图来 ...

  9. NS图绘制工具推荐

    世界上要画NS图的人肯定很少,这种无聊的东西= = 我根据个人经验和直觉,推荐三个套工具. 一.签字笔(铅笔+橡皮)+作业纸+拍照的手机 鉴于我以前手绘版ns图已经找不到了,就用室友之前画的做个例子. ...

  10. 【ZOJ 3502】Contest

    题 题意 n个问题,解决的顺序影响正确的概率,无论之前解决的问题是否答对,当前问题 j 答对概率为max{a[i][j]} (i为解决过的问题).求答对题目的最大期望和对应的答题顺序.T组测试,T ( ...