《你不知道的JavaScript(上卷)》笔记:词法作用域

词法作用域

  1. 词法作用域:定义在词法阶段的作用域。词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的。
  2. 函数作用域:如论函数何时被调用,也无论函数在何处被调用,函数的词法作用域都由函数被声明时所处的位置决定。
  3. 词法作用域只会查找一级标志符,比如a\b\c,如果代码饮用了foo.bar.baz,词法作用域查找只会试图查找foo标志符,
    找到这个变量后,对象属性访问规则会分别接管对bar和baz属性的访问。
  4. 欺骗词法:
    如果词法作用域完全由写代码期间函数所声明的位置来定义,怎样才能在运行时来“修改”词法作用域呢?

(1)eval:接受一个字符串作为参数,并将其中的内容视为好像在书写时就存在于程序中这个位置的代码。

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

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

    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被泄漏到全局变量中去

with 可以将一个没有或有多个属性的对象处理为一个完全隔离的词法作用域,因此这个对象的属性也会被处理为定义在这个作用域中的词法标志符。
5. 性能
JavaScript引擎会在编译阶段进行数项的性能优化,其中有些优化依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标志符。
eval(…)和with两个机制的副作用是引擎无法在编译时对作用域查找进行优化,因为引擎只能谨慎地认为这样的优化是无效的。
使用这其中任何一个机制都将导致代码运行变慢,不要使用它们。
6. ReferenceError 同作用域判别失败相关。TypeError则代表作用域判别成功,但是对结果的操作上非法或不合理的。

猜你喜欢

转载自blog.csdn.net/wuweitiandian/article/details/79434639