美文网首页
JavaScript 变量提升hoisting(8/28)

JavaScript 变量提升hoisting(8/28)

作者: BaibaiWang | 来源:发表于2017-08-29 11:36 被阅读0次

    JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
    以下两个实例将获得相同的结果:

    <script>
    x = 5; // 变量 x 设置为 5
    elem = document.getElementById("demo"); // 查找元素 
    elem.innerHTML = x;                     // 在元素中显示 x
    var x; // 声明 x
    </script>
    
    <script>
    var x; // 声明 x
    x = 5; // 变量 x 设置为 5
    elem = document.getElementById("demo"); // 查找元素 
    elem.innerHTML = x; 
    </script>
    
    • 下面代码条件语句if(!foo)并不会执行,为什么foo会被赋值为10:
    var foo = 1;
    function bar() {
        if (!foo) {
            var foo = 10;
        }
        alert(foo);
    }
    bar();
    
    • alert输出了1:
    var a = 1;
    function b() {
        a = 10;
        return;
        function a() {}
    }
    b();
    alert(a);
    

    C语言的一个例子:

    #include <stdio.h>
    int main() {
        int x = 1;
        printf("%d, ", x); // 1
        if (1) {
            int x = 2;
            printf("%d, ", x); // 2
        }
        printf("%d\n", x); // 1
    }
    

    程序依次输出了1,2,1; 因为在C语言中,我们有块级作用域(block-level scope)。在一个代码块的中变量并不会覆盖掉代码块外面的变量。
    JavaScript的一个例子:

    var x = 1;
    console.log(x); // 1
    if (true) {
        var x = 2;
        console.log(x); // 2
    }
    console.log(x); // 2
    

    输出的结果为1,2,2 if代码块中的变量覆盖了全局变量。
    那是因为JavaScript是一种函数级作用域(function-level scope)所以if中并没有独立维护一个scope,变量x影响到了全局变量x

    • JavaScript实现一种类似块级作用域的效果, 闭包:
    function foo() {
        var x = 1;
        if (x) {
            (function () {
                var x = 2;
                // some other code
            }());
        }
        // x is still 1.
        alert(x);
    }
        foo();
    
    Hoisting in Javascript

    在代码运行前,函数声明和变量定义通常会被解释器移动到其所在作用域的最顶部

    • 1
    function foo() {
        bar();
        var x = 1;
    }
    

    被代码解释器编译完后,将变成下面的形式:

    function foo() {
        var x;
        bar();
        x = 1;
    }
    
    • 2
    function foo() {
        if (false) {
            var x = 1;
        }
        return;
        var y = 1;
    }
    
    function foo() {
        var x, y;
        if (false) {
            x = 1;
        }
        return;
        y = 1;
    }
    

    变量的上升(Hoisting)只是其定义上升,而变量的赋值并不会上升。

    创建一个函数的方法有两种,一种是通过函数声明function foo(){}
    另一种是通过定义一个变量var foo = function(){}
    这两种在代码执行上的区别:

    function test() {
        foo(); // TypeError "foo is not a function"
        bar(); // "this will run!"
        var foo = function () { // function expression assigned to local variable 'foo'
            alert("this won't run!");
        }
        function bar() { // function declaration, given the name 'bar'
            alert("this will run!");
        }
    }
    test();
    

    foo()调用的时候报错了,而bar能够正常调用
    var foo首先会上升到函数体顶部,然而此时的foo为undefined,所以执行报错。而对于函数bar, 函数本身也是一种变量,所以也存在变量上升的现象,但是它是上升了整个函数,所以bar()才能够顺利执行。

    开头的两段代码:

    var foo = 1;
    function bar() {
        if (!foo) {
            var foo = 10;
        }
        alert(foo);
    }
    bar();
    

    实际为:

    var foo = 1;
    function bar() {
        var foo;
        if (!foo) {
            foo = 10;
        }
        alert(foo);
    }
    bar();
    
    var a = 1;
    function b() {
        a = 10;
        return;
        function a() {}
    }
    b();
    alert(a);
    

    实际为:

    var a = 1;
    function b() {
        function a() {}
        a = 10;
        return;
    }
    b();
    alert(a);
    

    改变了function a的值,从函数变为数值10,其实函数本身也可看做变量的定义,function 和 var 返回的类型不同而已。

    相关文章

      网友评论

          本文标题:JavaScript 变量提升hoisting(8/28)

          本文链接:https://www.haomeiwen.com/subject/zmhndxtx.html