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 相关文章推荐
jquery 之 $().hover(func1, funct2)使用方法
Jun 14 Javascript
获取数组中最大最小值方法js代码(自写)
Aug 12 Javascript
js实现Form栏显示全格式时间时钟效果代码
Aug 19 Javascript
详解AngularJS中的表单验证(推荐)
Nov 17 Javascript
实现一个简单的vue无限加载指令方法
Jan 10 Javascript
jquery表单提交带错误信息提示效果
Mar 09 Javascript
详解基于vue的移动web app页面缓存解决方案
Aug 03 Javascript
vue-router相关基础知识及工作原理
Mar 16 Javascript
JS实现面向对象继承的5种方式分析
Jul 21 Javascript
js的各种数据类型判断的介绍
Jan 19 Javascript
javascript实现日历效果
Jun 17 Javascript
vue3使用vuedraggable实现拖拽功能
Apr 06 Vue.js
理解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+AJAX实现无刷新注册(带用户名实时检测)
2007/01/02 PHP
PHP原理之异常机制深入分析
2010/08/08 PHP
php常用的url处理函数总结
2014/11/19 PHP
PHP ajax+jQuery 实现批量删除功能实例代码小结
2018/12/06 PHP
JavaScript面向对象知识串结(读JavaScript高级程序设计(第三版))
2012/07/17 Javascript
JS打开层/关闭层/移动层动画效果的实例代码
2013/05/11 Javascript
将json对象转换为字符串的方法
2014/02/20 Javascript
js实现日历可获得指定日期周数及星期几示例分享(js获取星期几)
2014/03/14 Javascript
单击和双击事件的冲突处理示例代码
2014/04/03 Javascript
Javascript MVC框架Backbone.js详解
2014/09/18 Javascript
JavaScript字符串对象substring方法入门实例(用于截取字符串)
2014/10/17 Javascript
HTML+CSS+JS实现完美兼容各大浏览器的TABLE固定列
2015/04/26 Javascript
javascript 中的继承实例详解
2017/05/05 Javascript
angular4实现tab栏切换的方法示例
2017/10/21 Javascript
[02:27]2018DOTA2亚洲邀请赛趣味视频之钓鱼大赛 谁是垂钓冠军?
2018/04/05 DOTA
python中尾递归用法实例详解
2015/04/28 Python
在Django框架中运行Python应用全攻略
2015/07/17 Python
Python的装饰器用法学习笔记
2016/06/24 Python
Python中装饰器高级用法详解
2017/12/25 Python
python实现图书馆研习室自动预约功能
2018/04/27 Python
基于Python解密仿射密码
2019/10/21 Python
Python并发请求下限制QPS(每秒查询率)的实现代码
2020/06/05 Python
浅析Python面向对象编程
2020/07/10 Python
CSS3 清除浮动的方法示例
2018/06/01 HTML / CSS
美国知名的摄影器材销售网站:Adorama
2017/02/01 全球购物
美国最大最全的亚洲购物网站:美国亚米网(Yamibuy)
2020/05/05 全球购物
飞利信loadrunner和软件测试笔试题
2012/09/22 面试题
网络工程与软件技术毕业生自荐信
2013/09/24 职场文书
中学教师实习自我鉴定
2013/09/28 职场文书
毕业生精彩的自我评价分享
2013/10/06 职场文书
人力资源部经理岗位职责规定
2014/02/23 职场文书
2014年物业管理工作总结
2014/11/21 职场文书
毕业实习单位意见
2015/06/04 职场文书
Python提取PDF指定内容并生成新文件
2021/06/09 Python
基于JavaScript实现省市联动效果
2021/06/22 Javascript
一篇文章带你复习java知识点
2021/06/28 Java/Android