[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 ”]
提示
- 在代码块中的变量声明会被隐式地提升到封闭函数的顶部
- 重声明变量被视为单个变量
- 考虑手动提升局部变量的声明,从而避免混淆
[Effective JavaScript 笔记] 第12条:理解变量声明提升的更多相关文章
- [Effective JavaScript 笔记] 第9条:始终声明局部变量
如果忘记将变量声明为局部变量,该变量将会隐式地转变为全局变量 function swap(a,i,j){ temp=a[i]; a[i]=a[j]; a[j]=temp; } 尽管该程序没有使用var ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记]第2章:变量作用域--个人总结
前言 第二章主要讲解各种变量作用域,通过这章的学习,接触到了很多之前没有接触过的东西,比如不经常用到的eval,命名函数表达式,with语句块等,下面是一个列表,我对各节的一点点个人总结,很多都是自己 ...
- 解读JavaScript中的Hoisting机制(js变量声明提升机制)
hoisting机制:javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 知识点一:javascript是没有 ...
- [Effective JavaScript 笔记] 第8条:尽量少用全局对象
初学者容易使用全局变量的原因 创建全局变量毫不费力,不需要任何形式的声明(只要在非函数里用var 你就可以得到一个全局变量) 写得代码简单,不涉及到大的项目或配合(写hello world是不会有什么 ...
- [Effective JavaScript 笔记]第16条:避免使用eval创建局部变量
js中的eval函数是一个强大.灵活的工具.强大的工具容易被滥用,所以了解是值得的.(本人只用过它来处理json数据).错误使用eval函数的方式一:允许它干扰作用域.调用eval函数会将其参数作为j ...
随机推荐
- Xamarin 的 MVVM 之 Caliburn.Micro
约定 Caliburn.Micro 以下简称 CMXamarin.Form 以下简称 XF 摘要CM 当前已释出 3.0 beta 版https://github.com/Caliburn-Micro ...
- 机器学习中的矩阵方法04:SVD 分解
前面我们讲了 QR 分解有一些优良的特性,但是 QR 分解仅仅是对矩阵的行进行操作(左乘一个酉矩阵),可以得到列空间.这一小节的 SVD 分解则是将行与列同等看待,既左乘酉矩阵,又右乘酉矩阵,可以得出 ...
- 传智168期JavaEE就业班 day04-dom
* 课程回顾: * js语法 * js的动态函数和匿名函数 * js动态函数 Function new Function(); * 匿名函数:没有名称的函数,起个名称 var add = functi ...
- 人工蜂群算法-python实现
ABSIndividual.py import numpy as np import ObjFunction class ABSIndividual: ''' individual of artifi ...
- SqlServer建表规范
一.数据库在建表时,一般默认字段如下,也算是标准字段吧 删除标志:DeletionStateCode 创建时间:CreateOn 创建人:CreateBy 更新时间:ModifiedOn 更新人:Mo ...
- DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录
相关学习资料 http://baike.baidu.com/link?url=77B3BYIuVsB3MpK1nOQXI-JbS-AP5MvREzSnnedU7F9_G8l_Kvbkt_O2gKqFw ...
- POJ3744Scout YYF I(求概率 + 矩阵快速幂)
Scout YYF I Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6757 Accepted: 1960 Descr ...
- Emgu学习之(二)——图像读取、显示、保存
visual Studio Community 2015 工程和源代码:http://pan.baidu.com/s/1o6u5Fdw 内容 在这篇文章中将提到以下内容: 从文件中读取图像 Image ...
- TP中二维数组的遍历输出
例子分析 <volist name="list" id="vo"> <volist name="vo['sub']" id ...
- C# 排序算法记录
class Program { static void Main(string[] args) { , , , , , , , , -, , , }; //假设一个最小的值 ]; ; i < a ...