zoukankan      html  css  js  c++  java
  • JavaScript变量提升的理解

    变量提升

    先说三句总结性的话:

    • let 的「创建」过程被提升了,但是初始化没有提升。

    • var 的「创建」和「初始化」都被提升了。

    • function 的「创建」「初始化」和「赋值」都被提升了。

    所以,我们要注意,这三种变量提升,含义是不同的。

    变量提升的规律

    在进入一个执行上下文后,先把 var 和 function 声明的变量前置,再去顺序执行代码。

    PS:作用域分为全局作用域和函数作用域,用var声明的变量,只在自己所在的所用域有效。

    我们举例来看看下面的代码。

    代码 1:

        console.log(fn);
        var fn = 1;
    
        function fn() {
        }
    
        console.log(fn);
    

    相当于:

        var fn = undefined;
    
        function fn() {
        }
    
        console.log(fn);
        fn = 1;
        console.log(fn);
    

    打印结果:

    代码 2:

        console.log(i);
        for (var i = 0; i < 3; i++) {
            console.log(i)
        }
    

    相当于:

        var i = undefined;
    
        console.log(i);
        for (i = 0; i < 3; i++) {
            console.log(i);
        }
    

    打印结果:

    代码 3:

        var a = 1;
    
        function fn() {
            a = 2;
            console.log(a)
            var a = 3;
            console.log(a)
        }
    
        fn();
        console.log(a);
    

    相当于:

        var a = undefined;
    
        function fn() {
            var a
    
            a = 2
            console.log(a)
            a = 3
            console.log(a)
        };
    
        a = 1;
        fn();
        console.log(a);
    

    打印结果:

    声明时的重名问题

    假设a被声明为变量,紧接着a又被声明为函数,原则是:声明会被覆盖(先来后到,就近原则)。

    PS:

    • 如果a已经有值,再用 var 声明是无效的。

    • 如果a已经有值,紧接着又被赋值,则赋值会被覆盖

    举例1:

        var fn;  //fn被声明为变量
        function fn() {// fn被声明为function,就近原则
    
        }
    
        console.log(fn); //打印结果:function fn(){}
    
    

    举例2:

        function fn() {}  //fn被声明为function,且此时fn已经被赋值,这个值就是function的对象
    
        var fn;   //fn已经在上一行被声明且已经有值, 再 var 无效,并不会重置为 undefined
    
        console.log(fn)  //打印结果:function fn(){}
    

    既然再var无效,但是再function,是有效的:

        function fn() {}  //fn被声明为function,且此时fn已经有值,这个值就是function的对象
    
        function fn() {   //此时fn被重复赋值,会覆盖上一行的值
            console.log('smyhvae');
        }
        console.log(fn)
    
    

    打印结果:

    函数作用域中的变量提升(两点提醒)

    提醒1:

    在函数作用域也有声明提前的特性:

    • 使用var关键字声明的变量,是在函数作用域内有效,而且会在函数中所有的代码执行之前被声明

    • 函数声明也会在函数中所有的代码执行之前执行

    因此,在函数中,没有var声明的变量都会成为全局变量,而且并不会提前声明。

    举例1:

            var a = 1;
    
            function foo() {
                console.log(a);
                a = 2;     // 此处的a相当于window.a
            }
    
            foo();
            console.log(a);   //打印结果是2
    
    

    上方代码中,foo()的打印结果是1。如果去掉第一行代码,打印结果是Uncaught ReferenceError: a is not defined

    提醒2:定义形参就相当于在函数作用域中声明了变量。

    
            function fun6(e) {
                console.log(e);
            }
    
            fun6();  //打印结果为 undefined
            fun6(123);//打印结果为123
    

    其他题目

        var a = 1;
        if (a > 0) {
            console.log(a);
            var a = 2;
        }
        console.log(a);
    
    

    打印结果:

    1
    
    2
    

    上方代码中,不存在块级作用域的概念。if语句中用var定义的变量,仍然是全局变量。

    顺便延伸一下,用let定义的变量,是在块级作用域内有效。

  • 相关阅读:
    【洛谷 2212】浇地Watering the Fields
    【洛谷 2504】聪明的猴子
    【洛谷 1991】无线通讯网
    【洛谷 3366】最小生成树_Prim
    Spark RDD中两种算子之一:常见Action算子小结
    Spark学习之路Spark之RDD
    Linux系统之pssh系列工具的使用
    MapReduce shuffle过程详解
    批量计算和流式计算
    关于IDEA破解后无法启动问题
  • 原文地址:https://www.cnblogs.com/qianguyihao/p/8619437.html
Copyright © 2011-2022 走看看