深入理解JavaScript变量的作用域

 

在学习JavaScript的变量作用域之前,我们应当明确几点:

  • JavaScript的变量作用域是基于其特有的作用域链的。
  • JavaScript没有块级作用域。
  • 函数中声明的变量在整个函数中都有定义。

1、JavaScript的作用域链

首先看下下面这段代码:

<script type="text/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">
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">
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">
function rain(){
var x = 1;
function man(){
x = 100;
}
man(); //调用man
alert( x ); //这里会弹出 100
}
rain(); //调用rain
</script>

上面得代码说明了,变量x在整个rain函数体内都可以使用,并可以重新赋值。由于这条规则,会产生“匪夷所思”的结果,观察下面的代码。

<script type="text/javascript">
var x = 1;
function rain(){
alert( x ); //弹出 'undefined',而不是1
var x = 'rain-man';
alert( x ); //弹出 'rain-man'
}
rain();
</script>

是由于在函数rain内局部变量x在整个函数体内都有定义( var x= 'rain-man',进行了声明),所以在整个rain函数体内隐藏了同名的全局变量x。这里之所以会弹出'undefined'是因为,第一个执行alert(x)时,局部变量x仍未被初始化。

所以上面的rain函数等同于下面的函数:

function rain(){
var x;
alert( x );
x = 'rain-man';
alert( x );
}

5、未使用var关键字定义的变量都是全局变量。

<script type="text/javascript">
function rain(){
x = 100; //声明了全局变量x并进行赋值
}
rain();
alert( x ); //会弹出100
</script>

这也是JavaScript新手常见的错误,无意之中留下的许多全局变量。

6、全局变量都是window对象的属性

<script type="text/javascript">
var x = 100 ;
alert( window.x );//弹出100
alert(x);
</script>

等同于下面的代码

<script type="text/javascript">
window.x = 100;
alert( window.x );
alert(x)
</script>

JS变量的作用域的更多相关文章

  1. js变量及其作用域(附例子及讲解)

    Javascript和Java.C这些语言不同,它是一种无类型.弱检测的语言.它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变量   工具/原料   Ch ...

  2. 详解js变量、作用域及内存

    详解js变量.作用域及内存 来源:伯乐在线 作者:trigkit4       原文出处: trigkit4    基本类型值有:undefined,NUll,Boolean,Number和Strin ...

  3. JS变量、作用域、内存

    写到这个题目<JS变量.作用域,内存>,我就不由自主想起了黄金三嫖客.可能是名字有点像,嗯,一定是这样子的! JS接触下来,应该是要比Java简单不少的,所以,要学好啊.立个flag半年后 ...

  4. js课程 1-4 js变量的作用域是怎样的

    js课程  1-4   js变量的作用域是怎样的 一.总结 一句话总结:只有在函数内部前面带var的变量为局部变量,局部变量只能在函数体内使用. 1.什么情况下会出现NaN类型的错误,举一例? Num ...

  5. js变量及其作用域

    Javascript和Java.C这些语言不同,它是一种无类型.弱检测的语言.它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变量   一.js变量的类型及 ...

  6. Js 变量的作用域

    变量的作用域 所有的变量作用域是指在哪里可用哪里不可用 局部作用域和全局作用域 在js中以函数来分割作用域 在函数里面就叫做局部作用域,在函数外面的就叫全局作用域 在函数里面如果省略var 关键字 那 ...

  7. js变量的作用域、变量的提升、函数的提升

    变量的作用域在函数之外声明的变量,叫做全局变量,因为它可被当前文档中的任何其他代码所访问.在函数内部声明的变量,叫做局部变量,因为它只能在当前函数的内部访问. ECMAScript 6 之前的 Jav ...

  8. js变量的作用域与函数作用域

    引自 1. 变量的作用域(var与let的区别) 在函数之外声明的变量,叫做全局变量,因为它可被当前文档中的任何其他代码所访问.在函数内部声明的变量,叫做局部变量,因为它只能在当前函数的内部访问. E ...

  9. 第 1 章 JS变量、作用域

    目录 一. 判断变量类型 二.作用域 和 上下文 1. 作用链 2. 上下文(this) 二.JS的解析机制 1. 预解析 三.垃圾收集 内存管理销毁 @(es5) 基本类型 引用类型 一. 判断变量 ...

随机推荐

  1. 一些有意思的APP

    1.简书:一个优雅的写作/阅读平台. 2.知乎:知识分享社区: 3.behance:设计者的圈子: 4.海词词典:电脑.手机同步查询的好帮手(电脑端快捷键:双击 Alt 弹出/关闭查询框,非常方便) ...

  2. SDWebImage实现原理--两张图带你看懂

    SDWebImage底层实现有沙盒缓存机制,主要由三块组成:1.内存图片缓存,2.内存操作缓存,3.磁盘沙盒缓存 SDWebImage GitHub地址 版本4.0.0 一.SDWebImage时序图 ...

  3. C++11 删除链表重复数值

    #include <memory> #include <iostream> #include <chrono> #include <thread> us ...

  4. 推送XML

    推送的连接地址如:www.baidu.com /// <summary> /// 提交数据 /// </summary> /// <param name="ms ...

  5. tar 压缩去除目录

    tar zcvf fd.tar.gz  *  --exclude=file1 --exclude=dir1 注意: 1.yes: --exclude=file1 no: --exclude file1 ...

  6. 斯坦福第六课:逻辑回归(Logistic Regression)

    6.1  分类问题 6.2  假说表示 6.3  判定边界 6.4  代价函数 6.5  简化的成本函数和梯度下降 6.6  高级优化 6.7  多类分类:一个对所有 6.1  分类问题 在分类问题中 ...

  7. 使用的组件:Jcrop

    JcropImage cropping for jQuery Jcrop 是一个功能强大的 jQuery 图像裁剪插件,结合后端程序(例如:PHP)可以快速的实现图片裁剪的功能. 官网地址:http: ...

  8. Kali Linux Web 渗透测试视频教程—第十四课-arp欺骗、嗅探、dns欺骗、session劫持

    Kali Linux Web 渗透测试视频教程—第十四课-arp欺骗.嗅探.dns欺骗.session劫持 文/玄魂 目录 Kali Linux Web 渗透测试—第十四课-arp欺骗.嗅探.dns欺 ...

  9. [MFC] MFC 获取指定窗口截图(大小可调)

    void screenShot(CRect rect,int left,int top,char *name){//截取窗口的大小,位置,名字(保存在默认路径下) CBitmap* m_pBitmap ...

  10. django上传文件

    template html(模板文件): <form enctype="multipart/form-data" method="POST" action ...