二、关于词法作用域

作用域有两种主要的工作模型:词法作用域动态作用域

词法作用域是在写代码或者说定义的时候确定的,而动态作用域是在运行时确定的。

词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用。

javascript所采用的是词法作用域模型

大部分语言编译器的第一个工作阶段就是词法化,词法作用域意味着作用域是由书写代码时函数声明的位置来决定的。让词法作用域根据词法关系保持书写时的自然关系不变是一种非常好的最佳实践,但是也存在两种欺骗词法作用域的方法:evalwith

a.eval(...)函数可以接受一个字符串为参数,并将其中的内容视为好像在书写时就存在于程序中这个位置的代码。它可以在运行期间修改书写期的词法作用域
例如:

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

b.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;
}

欺骗词法作用域为什么会导致性能下降?

javascript引擎会在编译阶段进行数项的性能优化,其中有些优化依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符,而这两个欺骗词法作用域的方法是在运行时改变词法作用域,使得引擎无法在编译的时候对作用域查找进行优化

你可能感兴趣的:(二、关于词法作用域)