第二章 词法作用域

欺骗词法,Javascript中有两种机制来实现这个目的, eval和with。

欺骗词法作用域会导致性能下降。

1.eval

function test(str, a){

  eval(str);  //欺骗

  console.log(a, b);

}

var b = 2;

test("var b = 3;", 1);  //1, 3

程序运行时,eval(str)会变换成var b=3; 此时test函数作用域中的b声明覆盖了全局作用域中b的声明。所以test中输出b是3。

2.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;

}

但在方便的同时,也会有隐患。考虑下面实例:

function test(obj){

  with(obj){

    a = 2;

  }

}

var o1 = {

  a : 3

};

 

var o2 = {

  b : 3

};

 

test(o1);

console.log(o1.a);    // 2

 

test(o2);

console.log(o2.a);    //  undefined

console.log(a);      //  2-----不好,a被泄露到全局作用域上了

 

由于o1中有a属性,所以test(o1)时,o1中的a被赋值为2;o2中没有a属性,test(o2)时,o2作用域中没有a的声明,再上一级test函数作用域中也没有a的声明,再上一级全局作用域中没有a的声明,由于a=2是LHS,所以在全局作用域中隐式创建了a的全局声明。于是在全局打印a的时候会输出2。

 

另外一个不推荐使用eval()和with()的原因是会被严格模式所限制。with被完全禁止,而在保留核心功能的前提下,间接或非安全地使用eval()也被禁止了。

posted on 2019-02-05 18:24  atomgame的记事本  阅读(57)  评论(0)    收藏  举报

导航