• JS 作用域与变量提升---JS 学习笔记(三)


    你知道下面的JavaScript代码执行时会输出什么吗?

    var foo = 1;
    function bar() {
        if (!foo) {
            var foo = 10;
        }
        console.log(foo);
    }
    bar();

    答案是“10”,吃惊吗?那么下面的可能会真的让你大吃一惊:

    var a = 1;
    function b() {
        a = 10;
        return;
        function a() {}
    }
    b();
    console.log(a);

    答案是 “1”。为什么会这样呢,这就涉及到 JS 里面的作用域、作用域链和提升的相关知识了。

    首先要明白 作用域和作用域链的内容(点击阅读),现在主要介绍提升。

    在 JavaScript 中,当遇到 var a = 1; 这个语句时,我们可能会这么认为,“为一个变量分配内存,给这个变量命名为 a,再把 1 保存进去”。然而这个过程并不完全正确。当编译器遇到 var a = 1 时,会做以下两个步骤:

    1. 遇到 var a ,首先会先看看当前的作用域中是否已经有 a,若有,就不再声明 a,若没有,就会在当前的作用域,创建一个 a

    2. 然后处理 a = 1 。先查看当前作用域,是否有 a 。如果有,就把 1 赋值给 a 。如果没有,就向上一个作用域中寻找 a,直到寻找到全局作用域。全局作用域中如果还没有,就会抛出异常。

    所以,当我们看到 var a = 1; 会认为这是一个声明,实际上这是两个声明, var a 和 a = 1 。第一个声明会在编译阶段进行,第二个声明会在原地等待执行。函数声明和变量声明总会被 JavaScript 的编译器提升到他们所在作用域的顶部。有了这些知识就可以解释上面的代码了

    第一段代码实际上如下图:在遇到并执行 bar()函数时,执行到 if 语句里面的 foo,此时会先查询 bar()函数的作用域内有没有声明 foo:

    若没有声明,就像上一个作用域中寻找 foo 有没有被声明。

    若声明了,就直接将声明提升到 bar 作用域里的顶部(foo = 10 留在原地按顺序等待执行),这样,foo 就是 undefined,!foo 就是 true,可以进入 if 循环。

    第二段代码实际上如下图:执行 b()时,首先就是 a = 10;这条语句,执行这条语句之前,先看 a 在 b 中是否被声明,若没有被声明就向上一个作用域中寻找 a ,现在的情况是,在 b 函数内部,a 以函数声明的方式,被声明了,那么就要把这个 a 函数声明提升到 a 所在的作用域的顶部,再按顺序执行后面的代码。

    对于提升总结的知识点:

    1. 函数声明和变量声明都会提升,但在同一个作用域相同名字的函数声明优先于变量声明。

    2. 变量声明会提升,但变量赋值的过程不会提升,会在原地等待被执行。

    3. 提升后,赋值语句会向前覆盖提升的内容。例子 2 中,b 函数的内部,最开始 a 是函数提升,a 的本质是函数,但是函数提升后,执行了一个赋值语句:a = 10;此时,a 就是一个 number 类型的变量了。

     

    对于这种情况,我们在写 JavasScript 代码的时候该怎么做呢?

    使用单 var 模式:避免变量提升所带来的问题

    /*jslint onevar: true [...] */
    function foo(a, b, c) {
        var x = 1,
            bar,
            baz = "something";
    }

    本文参考以下资料:

    颜海镜的博客:JavaScript作用域链和提升机制

    你不知道的JavaScript

    JavaScript高阶程序设计

  • 相关阅读:
    js的一些应用技巧
    js学习总结
    asp.net设置标题 兼MasterPage得使用
    IIS5、IIS6、IIS7的ASP.net 请求处理过程比较(转)
    .NET JSON.DLL
    大型网站架构演变和知识体系(转)
    JSON学习总结
    周华健,歌声伴我成长(三)
    研究方向
    周华健,歌声伴我长大(二)
  • 原文地址:https://www.cnblogs.com/rougan/p/10606755.html
Copyright © 2020-2023  润新知