JavaScript的变量作用域深入理解


Posted in Javascript onOctober 25, 2009

在学习JavaScript的变量作用域之前,我们应当明确几点:
a、JavaScript的变量作用域是基于其特有的作用域链的。
b、JavaScript没有块级作用域。
c、函数中声明的变量在整个函数中都有定义。

1、JavaScript的作用域链
首先看下下面这段代码:

<script type="text/javascript" language="javascript"> 
var rain = 1; 
function rainman(){ 
var man = 2; 
function inner(){ 
var innerVar = 4; 
alert(rain); 
} 
inner(); //调用inner函数 
} 
rainman(); //调用rainman函数 
</script>

观察alert(rain);这句代码。JavaScript首先在inner函数中查找是否定义了变量rain,如果定义了则使用inner函数中的rain变量;如果inner函数中没有定义rain变量,JavaScript则会继续在rainman函数中查找是否定义了rain变量,在这段代码中rainman函数体内没有定义rain变量,则JavaScript引擎会继续向上(全局对象)查找是否定义了rain;在全局对象中我们定义了rain = 1,因此最终结果会弹出'1'。
作用域链:JavaScript需要查询一个变量x时,首先会查找作用域链的第一个对象,如果以第一个对象没有定义x变量,JavaScript会继续查找有没有定义x变量,如果第二个对象没有定义则会继续查找,以此类推。
上面的代码涉及到了三个作用域链对象,依次是:inner、rainman、window。

2、函数体内部,局部变量的优先级比同名的全局变量高。

<script type="text/javascript" language="javascript"> 
var rain = 1; //定义全局变量 rain 
function check(){ 
var rain = 100; //定义局部变量rain 
alert( rain ); //这里会弹出 100 
} 
check(); 
alert( rain ); //这里会弹出1 
</script>

3、JavaScript没有块级作用域。
这一点也是JavaScript相比其它语言较灵活的部分。
仔细观察下面的代码,你会发现变量i、j、k作用域是相同的,他们在整个rain函数体内都是全局的。
<script type="text/javascript" language="javascript"> 
function rainman(){ 
/** 
* rainman函数体内存在三个局部变量 i j k 
*/ 
var i = 0; 
if( 1 ){ 
var j = 0; 
for( var k = 0 ; k < 3 ; k++ ){ 
alert( k ); //分别弹出 0 1 2 
} 
alert( k ); //弹出3 
} 
alert( j ); //弹出0 
} 
</script>

4、函数中声明的变量在整个函数中都有定义。
首先观察这段代码。
<script type="text/javascript" language="javascript"> 
function rain(){ 
var x = 1; 
function man(){ 
x = 100; 
} 
man(); //调用man 
alert( x ); //这里会弹出 100 
} 
rain(); //调用rain 
</script>

上面得代码说明了,变量x在整个rain函数体内都可以使用,并可以重新赋值。由于这条规则,会产生“匪夷所思”的结果,观察下面的代码。
这是由于在函数rain内局部变量x在整个函数体内都有定义( var x= 'rain-man',进行了声明),所以在整个rain函数体内隐藏了同名的全局变量x。这里之所以会弹出'undefined'是因为,第一个执行alert(x)时,局部变量x仍未被初始化。
<script type="text/javascript" language="javascript"> 
var x = 1; 
function rain(){ 
alert( x ); //弹出 'undefined',而不是1 
var x = 'rain-man'; 
alert( x ); //弹出 'rain-man' 
} 
rain() 
</script>

所以上面的rain函数等同于下面的函数。
function rain(){ 
var x; 
alert( x ); 
x = 'rain-man'; 
alert( x ); 
}

5、未使用var关键字定义的变量都是全局变量。
<script type="text/javascript" language="javascript"> 
function rain(){ 
x = 100; //声明了全局变量x并进行赋值 
} 
rain(); 
alert( x ); //会弹出100 
</script>

这也是JavaScript新手常见的错误,无意之中留下的许多全局变量。
6、全局变量都是window对象的属性
<script type="text/javascript" language="javascript"> 
var x = 100 ; 
alert( window.x );//弹出100 
alert(x); 
</script>

等同于下面的代码
<script type="text/javascript" language="javascript"> 
window.x = 100; 
alert( window.x ); 
alert(x) 
</script>
Javascript 相关文章推荐
灵活应用js调试技巧解决样式问题的步骤分享
Mar 15 Javascript
JS继承用法实例分析
Feb 05 Javascript
jQuery取消ajax请求的方法
Jun 09 Javascript
详解vue-Resource(与后端数据交互)
Jan 16 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
Feb 03 Javascript
js实现五星评价功能
Mar 08 Javascript
React学习笔记之事件处理(二)
Jul 02 Javascript
Angular项目中$scope.$apply()方法的使用详解
Jul 26 Javascript
vue实现的上传图片到数据库并显示到页面功能示例
Mar 17 Javascript
vue中使用sessionStorage记住密码功能
Jul 24 Javascript
Vue-Router基础学习笔记(小结)
Oct 15 Javascript
详解微信小程序回到顶部的两种方式
May 09 Javascript
理解JavaScript变量作用域更轻松
Oct 25 #Javascript
理解 JavaScript 预解析
Oct 25 #Javascript
WEB页子窗口(showModalDialog和showModelessDialog)使用说明
Oct 25 #Javascript
JavaScript弹簧振子超简洁版 完全符合能量守恒,胡克定理
Oct 25 #Javascript
javascript window对象属性整理
Oct 24 #Javascript
Javascript 模式实例 观察者模式
Oct 24 #Javascript
Jquery 弹出层插件实现代码
Oct 24 #Javascript
You might like
析构函数与php的垃圾回收机制详解
2013/10/28 PHP
php 过滤英文标点符号及过滤中文标点符号代码
2014/06/12 PHP
php实现购物车产品删除功能(2)
2020/07/23 PHP
PHP实现删除多重数组对象属性并重新赋值的方法
2017/06/07 PHP
php基于自定义函数记录log日志方法
2017/07/21 PHP
在Laravel5.6中使用Swoole的协程数据库查询
2018/06/15 PHP
ThinkPHP3.1.2 使用cli命令行模式运行的方法
2020/04/14 PHP
指定js可访问其它域名的cookie的方法
2007/09/18 Javascript
js两行代码按指定格式输出日期时间
2011/10/21 Javascript
ExtJS如何设置与获取radio控件的选取状态
2014/01/22 Javascript
Firefox中使用outerHTML的2种解决方法
2014/06/07 Javascript
javascript实现漂亮的拖动层,窗口拖拽特效
2015/04/24 Javascript
JavaScript DOM节点操作方法总结
2016/08/23 Javascript
如何通过非数字与字符的方式实现PHP WebShell详解
2017/07/02 Javascript
vue2实现搜索结果中的搜索关键字高亮的代码
2018/08/29 Javascript
axios 封装上传文件的请求方法
2018/09/26 Javascript
深入解析ES6中的promise
2018/11/08 Javascript
小程序如何自主实现拦截器的示例代码
2019/11/04 Javascript
JS自定义右键菜单实现代码解析
2020/07/16 Javascript
从零开始用webpack构建一个vue3.0项目工程的实现
2020/09/24 Javascript
[01:10]DOTA2次级职业联赛 - U5战队宣传片
2014/12/01 DOTA
Python使用chardet判断字符编码
2015/05/09 Python
Python中有趣在__call__函数
2015/06/21 Python
python3中dict(字典)的使用方法示例
2017/03/22 Python
如何基于Python实现数字类型转换
2020/02/07 Python
中东地区最大的奢侈品市场:The Luxury Closet
2019/04/09 全球购物
旅游管理专业学生求职信
2013/09/28 职场文书
远程教育心得体会
2014/01/03 职场文书
初中英语教学反思
2014/01/25 职场文书
大队委竞选演讲稿
2014/04/28 职场文书
团日活动总结
2014/04/28 职场文书
计算机专业毕业生求职信
2014/04/30 职场文书
2014年高数考试作弊检讨书
2014/12/14 职场文书
土木工程生产实习心得体会
2016/01/22 职场文书
Ajax实现异步加载数据
2021/11/17 Javascript
win10频率超出范围怎么办?win10老显示超出工作频率范围的解决方法
2022/07/07 数码科技