← 返回首页
Javascript基础教程(四十)
发表时间:2021-04-25 15:05:44
变量提升和函数提升

1.什么情况下会输出undefined

通常以下四种情况会出现undefined.

<script>

    let num;
    let person=new Object();
    //第一种情况:输出未初始化的变量num
    console.log(num);
    //第二种情况:获取未定义的变量a的类型
    console.log(typeof(a));

    function fn(){

    }
    //第三种情况:获取没有返回值的函数的结果
    console.log(fn());
    //第四种情况:获取对象未定义的属性。
    console.log(person.age);
</script>

2.什么是提升(Hosting)?

Javascript引擎会在解释JavaScript代码之前首先对齐进行编译,编译过程中的一部分工作就是找到所有的声明,并用合适的作用域将他们关联起来,这也正是词法作用域的核心内容。简单说就是在js代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端。

看下面实例:

<script>
    console.log(a);
    var a = "a";
    var foo = () => {
        console.log(a);
        var a = "a1";
    }
    foo();
</script>

输出结果: undefined undefined

1)变量提升

变量声明的提升是以变量所处的第一层词法作用域为“单位”的,即全局作用域中声明的变量会提升至全局最顶层,函数内声明的变量只会提升至该函数作用域最顶层。那么开始的一段代码经过预编译则变为:

<script>
    var a;
    console.log(a); //undefined
    var a = "a";
    var foo = () => {
        var a; //全局变量会被局部作用域中的同名变量覆盖
        console.log(a); //undefined
        var a = "a1";
    }
    foo();
</script>

ES6新增了let和const关键字,使得js也有了“块”级作用域,而且使用let和const 声明的变量和函数是不存在提升现象的,比较有利于我们养成良好的编程习惯。比如,上例改写如下:

<script>

    console.log(a);
    let a = "a";
    var foo = () => {
        console.log(a);
        let a = "a1";
    }
    foo();
</script>

运行结果: Uncaught ReferenceError: Cannot access 'a' before initialization

2)函数提升

<script>
    console.log(foo1); // [Function: foo1]
    foo1(); // foo1
    console.log(foo2); // undefined
    foo2(); // TypeError: foo2 is not a function
    function foo1 () {
        console.log("foo1");
    };
    var foo2 = function () {
        console.log("foo2");
    };

</script>

运行结果: ƒ foo1 () { console.log("foo1"); } foo1 undefined Uncaught TypeError: foo2 is not a function

这段代码经过函数提升后经过预编译则变为:

<script>
    //函数声明被提升到顶端
    function foo1 () {
        console.log("foo1");
    };
    console.log(foo1); // [Function: foo1]
    foo1(); // foo1

    var foo2;  //foo2 本质是变量提升。
    console.log(foo2); // undefined
    foo2(); // TypeError: foo2 is not a function

    var foo2 = function () {
        console.log("foo2");
    };

</script>

运行结果: ƒ foo1 () { console.log("foo1"); } foo1 undefined Uncaught TypeError: foo2 is not a function 所以说函数提升只会提升函数声明,而不会提升函数表达式。函数表达式本质还是变量提升。