词法作用域 --《你不知道的JS》

1.什么是词法作用域?

  词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变 。

2.欺骗词法

怎么在才能在运行中 “修改”词法作用域呢??

 

  答案:JavaScript中有两种机制实现这个目的,不过值得注意的是欺骗词法作用域会导致性能下降

  两种机制如下

  1.eval() 函数    ---魔鬼

    函数可以接受一个字符串为参数,这个字符相当于可以运行的JavaScript代码,在执行eval之后,引擎并不知道eval是以动态的方式进入的,并对词法环境进行修改。

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

  在执行eval之后,var b = 2; 会生成一个词法环境,即在foo作用域里面定义了b变量,console.log访问时首先会在自己的词法作用域里寻找a,b变量。类似的有setTimeout(),setInterval();

  3.with()

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

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

  3.性能

  JavaScript引擎会在编译阶段进行数项的性能优化。其中有些优化依赖于能够根据代码的词行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符 。如果引擎在代码中发现了eval(..)或with.

它只能简单地假设关于标识符位置的判断都是无效的,因为无法在词法分析阶段明确知道eval(..)会接收到什么代码,这些代码会如何对作用域进行修改,也无法知道传递给with用来创建新词法作用域的对象的内容到底是什么。 

 

posted @ 2017-10-18 21:16  im.lhc  阅读(3218)  评论(0)    收藏  举报