• 你不知道的JavaScript-2.词法作用域


    考虑以下代码:

    function foo(a) {
        var b = a * 2;
        function bar(c) {
            console.log( a, b, c );
        }
        bar( b * 3 );
    }
    foo( 2 ); // 2, 4, 12

    在这个例子中有三个逐级嵌套的作用域。

    1.  包含着整个全局作用域,其中只有一个标识符: foo 。
    2.  包含着 foo 所创建的作用域,其中有三个标识符: a 、 bar 和 b 。
    3.  包含着 bar 所创建的作用域,其中只有一个标识符: c 。


    全局变量会自动成为全局对象(比如浏览器中的 window 对象)的属性,因此可以不直接通过全局对象的词法名称,而是间接地通过对全局对象属性的引用来对其进行访问。
    window.a
    通过方式可以访问那些被同名局部变量所遮蔽的全局变量。但非全局的变量如果被遮蔽了,无论如何都无法被访问到。


    eval

    JavaScript 中的 eval(..) 函数可以接受一个字符串为参数,并将其中的内容视为好像在书写时就存在于程序中这个位置的代码。换句话说,可以在你写的代码中用程序生成代码并运行,就好像代码是写在那个位置的一样。

    考虑以下代码:

    function foo(str, a) {
        eval( str ); // 欺骗!
        console.log( a, b );
    }
    var b = 2;
    foo( "var b = 3;", 1 ); // 1, 3

    eval(..) 调用中的 "var b = 3;" 这段代码会被当作本来就在那里一样来处理。
    由于那段代码声明了一个新的变量 b ,因此它对已经存在的 foo(..) 的词法作用域进行了修改。事实上,和前面提到的原理一样,这段代码实际上在 foo(..) 内部创建了一个变量 b ,并遮蔽了外部(全局)作用域中的同名变量。


    with

    with 通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。

    // 单调乏味的重复 "obj"
    obj.a = 2;
    obj.b = 3;
    obj.c = 4;
    // 简单的快捷方式
    with (obj) {
        a = 3;
        b = 4;
        c = 5;
    }

    但实际上这不仅仅是为了方便地访问对象属性。考虑如下代码:

    function foo(obj) {
        with (obj) {
          a = 2;
        }
    }
    var o1 = {
        a: 3
    };
    var o2 = {
        b: 3
    };
    foo( o1 );
    console.log( o1.a ); // 2
    foo( o2 );
    console.log( o2.a ); // undefined
    console.log( a ); // 2——不好,a 被泄漏到全局作用域上了!    

    可以注意到一个奇怪的副作用,实际上 a = 2 赋值操作创建了一个全局的变量 a 。这是怎么回事?

    可以这样理解,当我们传递 o1 给 with 时, with 所声明的作用域是 o1 ,而这个作用域中含有一个同 o1.a 属性相符的标识符。但当我们将 o2 作为作用域时,其中并没有 a 标识符,因此进行了正常的 LHS 标识符查找.

    o2 的作用域、 foo(..) 的作用域和全局作用域中都没有找到标识符 a ,因此当 a=2 执行时,自动创建了一个全局变量(因为是非严格模式)。


    eval、with 会导致引擎无法在编译时对作用域查找进行优化,从而影响性能。

  • 相关阅读:
    stat 命令家族(2)- 详解 pidstat
    stat 命令家族(1)- 详解 vmstat
    Linux常用命令
    Linux常用命令
    Linux常用命令
    Linux常用命令
    Linux常用命令
    Linux常用命令
    打通MySQL架构和业务的任督二脉
    PostgreSQL JOIN LATERAL
  • 原文地址:https://www.cnblogs.com/kjcy8/p/7615329.html
Copyright © 2020-2023  润新知