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操作textarea方法集合封装(兼容IE,firefox)
Feb 22 Javascript
JavaScript 匿名函数(anonymous function)与闭包(closure)
Oct 04 Javascript
extjs4 treepanel动态改变行高度示例
Dec 17 Javascript
JavaScript初学者建议:不要去管浏览器兼容
Feb 04 Javascript
sogou地图API用法实例教程
Sep 11 Javascript
浅析使用BootStrap TreeView插件实现灵活配置快递模板
Nov 28 Javascript
js实现彩色条纹滚动条效果
Mar 15 Javascript
JavaScript中in和hasOwnProperty区别详解
Aug 04 Javascript
vue项目中导入swiper插件的方法
Jan 30 Javascript
微信小程序switch开关选择器使用详解
Jan 31 Javascript
微信小程序之事件交互操作实例分析
Dec 03 Javascript
一篇文章介绍redux、react-redux、redux-saga总结
May 23 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
模拟OICQ的实现思路和核心程序(二)
2006/10/09 PHP
关于Appserv无法打开localhost问题的解决方法
2009/10/16 PHP
将文件夹压缩成zip文件的php代码
2009/12/14 PHP
利用curl抓取远程页面内容的示例代码
2013/07/23 PHP
destoon二次开发常用数据库操作
2014/06/21 PHP
PHP实现的简单留言板功能示例【基于thinkPHP框架】
2018/12/07 PHP
PHP _construct()函数讲解
2019/02/03 PHP
php 使用expat方式解析xml文件操作示例
2019/11/26 PHP
提高代码性能技巧谈—以创建千行表格为例
2006/07/01 Javascript
jquery中获取select选中值的代码
2011/06/27 Javascript
JS根据变量保存方法名并执行方法示例
2014/04/04 Javascript
解释&amp;&amp;和||在javascript中的另类用法
2014/07/28 Javascript
深入理解JavaScript系列(27):设计模式之建造者模式详解
2015/03/03 Javascript
javascript控制层显示或隐藏的方法
2015/07/22 Javascript
原生javascript实现的一个简单动画效果
2016/03/30 Javascript
jquery表单验证插件validation使用方法详解
2017/01/20 Javascript
微信小程序自定义模态对话框实例详解
2017/08/16 Javascript
微信小程序中post方法与get方法的封装
2017/09/26 Javascript
webpack4.0打包优化策略整理小结
2018/03/30 Javascript
浅谈Vue路由快照实现思路及其问题
2018/06/07 Javascript
微信小程序登录态和检验注册过没的app.js写法
2019/05/22 Javascript
nuxt踩坑之Vuex状态树的模块方式使用详解
2019/09/06 Javascript
vue.js使用v-model实现父子组件间的双向通信示例
2020/02/05 Javascript
python算法演练_One Rule 算法(详解)
2017/05/17 Python
详解pandas安装若干异常及解决方案总结
2019/01/10 Python
Python如何爬取微信公众号文章和评论(基于 Fiddler 抓包分析)
2019/06/28 Python
Python文字截图识别OCR工具实例解析
2020/03/05 Python
Python xlwt模块使用代码实例
2020/06/10 Python
Python pexpect模块及shell脚本except原理解析
2020/08/03 Python
数字天堂软件测试面试题
2012/12/23 面试题
介绍一下Java的事务处理
2012/12/07 面试题
九月份红领巾广播稿
2014/01/22 职场文书
开展批评与自我批评发言材料
2014/05/15 职场文书
治安消防安全责任书
2014/07/23 职场文书
治庸问责工作总结
2015/08/11 职场文书
解决Golang time.Parse和time.Format的时区问题
2021/04/29 Golang