前言

Javascript中的变量定义方式有以下三种方式:
1、直接定义变量,var与let均不写;

a = 10;

2、使用var关键字定义变量

var a = 10;

3、使用let关键字定义变量

let a = 10;

这三种方式有什么区别呢?
JavaScript全局变量和局部变量又是什么呢?
可以带着这两个问题往下看。

变量的作用域

变量是有作用域的,大多数语言中的变量的作用域都有全局变量和局部变量之分。
首先我们建立一个文件test1.html,从中输入以下代码:

<script type="text/javascript">
    //在函数外使用var关键字声明变量test_var1
    var test_var1 = "变量1";
    //定义函数testFun
    function testFun(){
        //在函数中定义变量没加任何关键字的变量test_var2
        test_var2 = "变量2";
        //函数内使用var关键字定义的test_var3
        var test_var3 = "变量3";
    }
    //函数执行
    testFun();
    alert(test_var1 + "\n" + test_var2);
    alert(test_var3);
</script>

在浏览器打开我们的html页面,可以看到只弹出了一个弹窗:

第二个弹窗为什么没有成功弹出呢?
我们按F12,看一下报错内容:

由此可以看出 test_var3 在函数执行后是没有被定义的。说明在函数体内用 var 关键字声明的变量 test_var3 是局部变量;
在函数体外使用 var 关键字定义的变量test_var1 和在函数体内未用任何关键字定义的变量 test_var2 是全局变量。

得出结论:
在函数体外使用var关键字定义的变量和在函数体内未用任何关键字声明的变量是全局变量,在函数体内使用var关键字声明的变量是局部变量。

var声明的全局变量和局部变量同名

我们建立一个文件test2.html,从中输入以下代码:

<script type="text/javascript">
    //在函数外使用var关键字声明变量test_var
    var test_var = "函数体外的变量";
    //定义函数testFun
    function testFun(){
        //函数内使用var关键字声明变量test_var
        var test_var = "函数体内的变量";
        //弹窗弹出test_var
        alert(test_var);
    }
    //函数执行
    testFun();
    alert(test_var);
</script>

打开该文件,会弹出两次弹窗,分别是:


点击确定后还会弹窗一次:

在函数体外定义的全局变量test_var,但是在函数体内又定义了局部变量test_var ,在函数中弹出的test_var是函数体内的局部变量覆盖函数体外的全局变量的结果,当离开函数后,局部变量失效,将会看到全局变量。

JavaScript中的变量有块范围吗?

JavaCC++等语言中,在 if块循环块中定义的变量,出了该块之后将,不能继续访问。那JavaScript中是否也如此呢?

我们建立一个文件test3.html,从中输入以下代码:

<script type="text/javascript">
    //定义函数testFun
    function testFun(){
        //函数内使用var关键字声明变量test_var
        var test_var1 = "1";
        //if代码块
        if(test_var1 == "1"){
            //定义变量test_var2
            var test_var2 = 10;
            //for代码块
            for(var i = 0; i < 5; i++){
                //打印输出i
                document.write(i);
            }
        }
        //在if块外访问test_var2
        alert(test_var2);
        //在循环体外访问i
        alert(i);
    }
    //函数执行
    testFun();
</script>

我们可以看到两个弹窗:


并且能看到页面上的输出

由此我们可以知道:
在函数体内中的 if 块和循环体内定义的变量,在函数内都是可以访问的。

变量提升

前面介绍中已经知道:局部变量和全局变量同名时,局部变量会覆盖全局变量。
我们定义test4.html,输入以下代码:

<script type="text/javascript">
    //在函数外使用var关键字声明变量test_var
    var test_var = "函数外的test_var";
    //定义函数testFun
    function testFun(){
        //打印输出test_var
        document.writeln(test_var + "<br>");
        //函数内使用var关键字定义的test_var
        var test_var = "函数内的test_var";
        //再次打印输出test_var
        document.writeln(test_var + "<br>");
    }
    //函数执行
    testFun();
</script>

输出如下:

在输出全局变量时,居然输出的是underfined,这是什么情况呢?
这便是JavaScript的变量提升机制起了”作用“。下面介绍一下变量提升:
在函数体内变量声明总会被解释器”提升“到函数体的顶部,
那么上面的代码,会变成如下情况:

<script type="text/javascript">
    //在函数外使用var关键字声明变量test_var
    var test_var = "函数外的test_var";
    //定义函数testFun
    function testFun(){
        //声明被提升到顶部,但是未被赋值
        var test_var;
        //打印输出test_var
        document.writeln(test_var + "<br>");
        //给test_var赋值
        test_var = "函数内的test_var";
        //再次打印输出test_var
        document.writeln(test_var + "<br>");
    }
    //函数执行
    testFun();
</script>

由此可见,变量提升只提升声明部分,不提示赋值部分。

我们定义test5.html,输入以下代码:

<script type="text/javascript">
    //在函数外使用var关键字声明变量test_var1
    var test_var1 = "函数外的test_var1";
    //在函数外使用var关键字声明变量test_var2
    var test_var2 = "函数外的test_var2";
    //定义函数testFun
    function testFun(){
        //打印输出test_var1
        document.writeln(test_var1 + "<br>");
        //打印输出test_var2
        document.writeln(test_var2 + "<br>");
        //for循环的条件为假不会被执行
        for(;-1>5;){
            //在函数内使用var关键字声明变量test_var1
            var test_var1 = "函数内的test_var1";
        }
        return;
        //return后面的语句不会被执行
        //在函数内使用var关键字声明变量test_var2
        var test_var2 = "函数内的test_var2";
    }
    //函数执行
    testFun();
</script>

输出如下:


在函数内的test_var1test_var2 的变量定义根本不会被执行,为何还是输出undefined呢?
这也是变量提升起的”作用“。

let关键字定义变量

从前面我们可以看到,var定义的变量没有块作用域,还有变量提升机制,为了克服这些问题,便引入了let关键字。

我们定义test6.html,输入以下代码:

<script type="text/javascript">
    //循环体
    for(let v = 0;v < 5;v++){
    //在循环体内输出v
        console.log(v);
    }
    //在循环体外输出v
    console.log(v);
</script>

按F12,打开console,看到输出如下:

可以看到在循环体外不能访问循环体内定义的变量。

我们定义test7.html,输入以下代码:

<script type="text/javascript">
    //在函数外使用let关键字声明变量test_var
    let test_var = "函数外的test_var";
    //定义函数testFun
    function testFun(){
        //打印输出test_var
        console.log(test_var);
        //在函数内使用let关键字声明变量test_var
        let test_var = "函数内的test_var"
        //打印输出test_var
        console.log(test_var);   
    }
    //函数执行
    testFun();
</script>

按F12,打开console,看到输出如下:


这是因为函数内有和全局变量同名的局部变量,会覆盖掉全局变量,但是let关键字声明的变量并没有提升机制,所以会报错。

小结

本文介绍了JavaScript中的局部变量和全局变量的知识和var,let声明变量的区别。给我们的启示是如果浏览器支持let关键字,那么就尽量用let来避免变量提升机制等情况。

欢迎关注

扫下方二维码即可关注,微信公众号:code随笔

Javascript中的局部变量、全局变量的详解与var、let的使用区别的更多相关文章

  1. JavaScript中的鼠标滚轮事件详解

    JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ...

  2. JavaScript中typeof和instanceof深入详解

    这次主要说说javascript的类型判断函数typeof和判断构造函数原型instanceof的用法和注意的地方. typeof 先来说说typeof吧.首先需要注意的是,typeof方法返回一个字 ...

  3. JavaScript 中 apply 、call 的详解

    apply 和 call 的区别 ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已. 原文作者:林 ...

  4. Javascript中的this关键字用法详解

    在javascript里面,this是一个特殊的对象,它不像其他编程语言那样,是存储在实例中的值,直接指向此实例. 而是作为一个单独的指针,在不同的情况之下,指向不同的位置,这也是为什么我们会将它搞混 ...

  5. JavaScript中事件委托(事件代理)详解

    在JavaScript的事件中,存在事件委托(事件代理),那么什么是事件委托呢? 事件委托在生活中的例子: 有三个同事预计会在周一收到快递.为签收快递,有两种办法:一是三个人在公司门口等快递:二是委托 ...

  6. javascript中6种基本数据类型详解

    javascript中有5中数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String,还有一种复杂数据类型——object,object本质是由一组键值 ...

  7. JavaScript中继承的实现方法--详解

    最近看<JavaScript王者归来>中关于实现继承的方法,做了一些小总结: JavaScript中要实现继承,其实就是实现三层含义:1.子类的实例可以共享父类的方法:2.子类可以覆盖父类 ...

  8. JavaScript中定义类的方式详解

    本文实例讲述了JavaScript中定义类的方式.分享给大家供大家参考,具体如下: Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的exte ...

  9. Javascript中的apply与call详解

    JavaScript中有一个call和apply方法,其作用基本相同,但也有略微的区别. 一.方法定义 1.call 方法 语法:call([thisObj[,arg1[, arg2[, [,.arg ...

随机推荐

  1. 吴裕雄--天生自然 JAVA开发学习:异常处理

    try { // 程序代码 }catch(ExceptionName e1) { //Catch 块 } import java.io.*; public class ExcepTest{ publi ...

  2. 黑马eesy_15 Vue:04.Vue案例(ssm环境搭建)

    黑马eesy_15 Vue:02.常用语法 黑马eesy_15 Vue:03.生命周期 黑马eesy_15 Vue:04.Vue案例(ssm环境搭建) 黑马eesy_15 Vue:04.综合案例(前端 ...

  3. RDD(五)——action

    reduce(func) 通过func函数聚集RDD中的所有元素并得到最终的结果,先聚合分区内数据,再聚合分区间数据.Func函数决定了聚合的方式. def main(args: Array[Stri ...

  4. P - Atlantis (线段树+扫描线)

      There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Som ...

  5. Memcache工作原理

    1       Memcache是什么 Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的 ...

  6. VBA引用管理工具(可用于32、64位Office,Win7 Win10均可)

    VBAReferenceManager安装和使用方法,操作请看动态图: 下载地址: VBAReferenceManager.zip

  7. 吴裕雄--天生自然 R语言开发学习:数据集和数据结构

    数据集的概念 数据集通常是由数据构成的一个矩形数组,行表示观测,列表示变量.表2-1提供了一个假想的病例数据集. 不同的行业对于数据集的行和列叫法不同.统计学家称它们为观测(observation)和 ...

  8. dim|lobby|trifle|

    ADJ-GRADED 勉强的;不情愿的If you are reluctant to do something, you are unwilling to do it and hesitate bef ...

  9. 【数据结构】B树与B+树

    定义 B 树可以看作是对2-3查找树的一种扩展,即他允许每个节点有M-1个子节点. 根节点至少有两个子节点 每个节点有M-1个key,并且以升序排列 位于M-1和M key的子节点的值位于M-1 和M ...

  10. bat连接映射盘

    net use h: \\IP地址\目录 "密码" /user:"用户名"