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 字符串处理函数使用小结
Dec 02 Javascript
Jquery为单选框checkbox绑定单击click事件
Dec 18 Javascript
jQuery插件bxSlider实现响应式焦点图
Apr 12 Javascript
H5上传本地图片并预览功能
May 08 Javascript
jQuery插件DataTables分页开发心得体会
Aug 22 jQuery
剖析Angular Component的源码示例
Mar 23 Javascript
vue项目中公用footer组件底部位置的适配问题
May 10 Javascript
JavaScript实现的文本框placeholder提示文字功能示例
Jul 25 Javascript
解决betterScroll在vue中存在图片时,出现拉不动的问题
Sep 27 Javascript
ES6 Iterator接口和for...of循环用法分析
Jul 31 Javascript
在vue+element ui框架里实现lodash的debounce防抖
Nov 13 Javascript
最全vue的vue-amap使用高德地图插件画多边形范围的示例代码
Jul 17 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实现冒泡排序的简单实例
2016/05/26 PHP
PHP单链表的实现代码
2016/07/05 PHP
php实现HTML实体编号与非ASCII字符串相互转换类实例
2016/11/02 PHP
PHP 表单提交及处理表单数据详解及实例
2016/12/27 PHP
php5.x禁用eval的操作方法
2018/10/19 PHP
PHP中$GLOBALS与global的区别详解
2019/03/21 PHP
Laravel 5.4前后台分离,通过不同的二级域名访问方法
2019/10/13 PHP
js 判断checkbox是否选中的实现代码
2010/11/23 Javascript
jQuery使用数组编写图片无缝向左滚动
2012/12/11 Javascript
JS实现下拉框的动态添加(附效果)
2013/04/03 Javascript
模拟多级复选框效果的jquery代码
2013/08/13 Javascript
Javascript 按位左移运算符使用介绍(
2014/02/04 Javascript
页面加载完毕后滚动条自动滚动一定位置
2014/02/20 Javascript
js实现温度计时间样式代码分享
2015/08/21 Javascript
jQuery源码分析之init的详细介绍
2017/02/13 Javascript
vue2.0 自定义组件的方法(vue组件的封装)
2018/06/05 Javascript
video.js 实现视频只能后退不能快进的思路详解
2018/08/09 Javascript
JavaScript深入V8引擎以及编写优化代码的5个技巧
2019/06/24 Javascript
微信小程序select下拉框实现源码
2019/11/08 Javascript
微信小程序仿淘宝热搜词在搜索框中轮播功能
2020/01/21 Javascript
Vue中nprogress页面加载进度条的方法实现
2020/11/13 Javascript
python3新特性函数注释Function Annotations用法分析
2016/07/28 Python
Python 使用类写装饰器的小技巧
2018/09/30 Python
Pytorch中的VGG实现修改最后一层FC
2020/01/15 Python
python正则表达式实例代码
2020/03/03 Python
css3 图片圆形显示 如何CSS将正方形图片显示为圆形图片布局
2014/10/10 HTML / CSS
海外淘书首选:AbeBooks
2017/07/31 全球购物
简述进程的启动、终止的方式以及如何进行进程的查看
2014/02/20 面试题
thinkphp5 redis缓存新增方法实例讲解
2021/03/24 PHP
六十大寿答谢词
2014/01/12 职场文书
总经理工作职责范文
2014/03/14 职场文书
客户经理岗位职责
2015/01/31 职场文书
慰问信格式
2015/02/14 职场文书
医院员工辞职信范文
2015/05/12 职场文书
win10+anaconda安装yolov5的方法及问题解决方案
2021/04/29 Python
nginx搭建NFS网络文件系统
2022/04/14 Servers