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 相关文章推荐
Javascript中正则表达式的全局匹配模式分析
Apr 26 Javascript
form.submit()不能提交表单的错误原因及解决方法
Oct 13 Javascript
jQuery实现长按按钮触发事件的方法
Feb 02 Javascript
jQuery头像裁剪工具jcrop用法实例(附演示与demo源码下载)
Jan 22 Javascript
JS判断字符串字节数并截取长度的方法
Mar 05 Javascript
jQuery 限制输入字符串长度
Jun 20 Javascript
浅谈Vue的基本应用
Dec 27 Javascript
使用JS在浏览器中判断当前网络连接状态的几种方法
May 05 Javascript
本地存储localStorage用法详解
Jul 31 Javascript
jQuery取得元素标签名称小结(附代码)
Aug 16 jQuery
vue-router传递参数的几种方式实例详解
Nov 13 Javascript
vue 解决兄弟组件、跨组件深层次的通信操作
Jul 27 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
Ping服务的php实现方法,让网站快速被收录
2012/02/04 PHP
php结合mysql与mysqli扩展处理事务的方法
2016/06/29 PHP
php和vue配合使用技巧和方法
2019/05/09 PHP
PHP单文件上传原理及上传函数的封装操作示例
2019/09/02 PHP
自适应高度框架 ----属个人收藏内容
2007/01/22 Javascript
关于实现代码语法标亮 dp.SyntaxHighlighter
2007/02/02 Javascript
Javascript下的keyCode键码值表
2007/04/10 Javascript
JavaScript this 深入理解
2009/07/30 Javascript
js DOM的学习笔记
2011/12/22 Javascript
jquery实现一个简单好用的弹出框
2014/09/26 Javascript
JavaScript实现点击按钮直接打印
2016/01/06 Javascript
基于vuejs+webpack的日期选择插件
2020/05/21 Javascript
Google 爬虫如何抓取 JavaScript 的内容
2017/04/07 Javascript
详解angularjs 关于ui-router分层使用
2017/06/12 Javascript
AngularJs+Bootstrap实现漂亮的计算器
2017/08/10 Javascript
详解Angular4 路由设置相关
2017/08/26 Javascript
Vue2.0基于vue-cli+webpack同级组件之间的通信教程(推荐)
2017/09/14 Javascript
为vue-router懒加载时下载js的过程中添加loading提示避免无响应问题
2018/04/03 Javascript
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
2018/08/28 jQuery
webpack实现一个行内样式px转vw的loader示例
2018/09/13 Javascript
JS实现随机抽取三人
2019/11/06 Javascript
微信小程序实现时间戳格式转换
2020/07/20 Javascript
浅析Python的web.py框架中url的设定方法
2016/07/11 Python
python通过百度地图API获取某地址的经纬度详解
2018/01/28 Python
python DataFrame 取差集实例
2019/01/30 Python
python实现高斯判别分析算法的例子
2019/12/09 Python
浅谈pytorch中torch.max和F.softmax函数的维度解释
2020/06/28 Python
自定义Django_rest_framework_jwt登陆错误返回的解决
2020/10/18 Python
Python性能测试工具Locust安装及使用
2020/12/01 Python
next在python中返回迭代器的实例方法
2020/12/15 Python
Guess美国官网:美国知名服装品牌
2019/04/08 全球购物
写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围)
2014/09/05 面试题
舞蹈兴趣小组活动总结
2014/07/07 职场文书
爬山的活动方案
2014/08/16 职场文书
学生会个人总结范文
2015/02/15 职场文书
2016年社区“我们的节日·中秋节”活动总结
2016/04/05 职场文书