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 Firefox与IE 替换节点的方法
Feb 24 Javascript
给事件响应函数传参数的四种方式小结
Dec 05 Javascript
js动态创建上传表单通过iframe模拟Ajax实现无刷新
Feb 20 Javascript
JavaScript获取指定元素位置的方法
Apr 08 Javascript
jquery调整表格行tr上下顺序实例讲解
Jan 09 Javascript
基于JS代码实现实时显示系统时间
Jun 16 Javascript
a标签跳转到指定div,jquery添加和移除class属性的实现方法
Oct 10 Javascript
性能优化篇之Webpack构建速度优化的建议
Apr 03 Javascript
JavaScript 中的无穷数(Infinity)详解
Feb 13 Javascript
基于JS实现计算24点算法代码实例解析
Jul 23 Javascript
解决nuxt 自定义全局方法,全局属性,全局变量的问题
Nov 05 Javascript
JavaScript实现淘宝商品图切换效果
Apr 29 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
自动跳转中英文页面
2006/10/09 PHP
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
2013/07/03 PHP
解决php接收shell返回的结果中文乱码问题
2014/01/23 PHP
PHP 数组遍历foreach语法结构及实例
2016/06/13 PHP
PHP 数组基本操作方法详解
2016/06/17 PHP
PHP中TP5 上传文件的实例详解
2017/07/31 PHP
php微信公众号开发之简答题
2018/10/20 PHP
prototype 1.5 &amp; scriptaculous 1.6.1 学习笔记
2006/09/07 Javascript
javascript和HTML5利用canvas构建猜牌游戏实现算法
2013/07/17 Javascript
jquery得到font-size属性值实现代码
2013/09/30 Javascript
javascript实现的弹出层背景置灰-模拟(easyui dialog)
2013/12/27 Javascript
jquery.uploadify插件在chrome浏览器频繁崩溃解决方法
2015/03/01 Javascript
基于jQuery的ajax方法封装
2016/07/14 Javascript
微信小程序中使元素占满整个屏幕高度实现方法
2016/12/14 Javascript
[js高手之路]从原型链开始图解继承到组合继承的产生详解
2017/08/28 Javascript
vue.js系列中的vue-fontawesome使用
2018/02/10 Javascript
在Vue组件中获取全局的点击事件方法
2018/09/06 Javascript
vue 本地服务不能被外部IP访问的完美解决方法
2018/10/29 Javascript
Python  连接字符串(join %)
2008/09/06 Python
利用Python生成文件md5校验值函数的方法
2017/01/10 Python
python logging日志模块的详解
2017/10/29 Python
django使用html模板减少代码代码解析
2017/12/12 Python
Python解决八皇后问题示例
2018/04/22 Python
TensorFlow实现随机训练和批量训练的方法
2018/04/28 Python
Python+selenium 获取浏览器窗口坐标、句柄的方法
2018/10/14 Python
pandas 把数据写入txt文件每行固定写入一定数量的值方法
2018/12/28 Python
python turtle库画一个方格和圆实例
2019/06/27 Python
tensorflow 自定义损失函数示例代码
2020/02/05 Python
配置python的编程环境之Anaconda + VSCode的教程
2020/03/29 Python
基于tf.shape(tensor)和tensor.shape()的区别说明
2020/06/30 Python
CSS3 Flex 弹性布局实例代码详解
2018/11/01 HTML / CSS
幼教简历自我评价
2014/01/28 职场文书
2015年学校工作总结范文
2015/04/20 职场文书
通用员工手册范本
2015/05/14 职场文书
聊聊mysql都有哪几种分区方式
2022/04/13 MySQL
Win11右下角图标点了没反应怎么办?Win11点击右下角图标无反应解决方法汇总
2022/07/07 数码科技