作用域完全由写代码时的函数声明所决定,js有两种机制可以实现”破坏“我们对作用域的常规理解,通过eval()和with()。
1. eval()函数接受字符串为参数,并将其中的声明提升到eval()函数所在的位置。
function foo(str,num) { eval(str); console.log(b,num); //1,33 } var b = 2; foo("var b = 1;",33);
function foo(str,num) { console.log(b,num); //2,33 } var b = 2; foo("var b = 1;",33);
在严格模式的程序中,eval(...)函数在运行时有自己的作用域,即其中的申明无法修改所在的作用域。
2. with()通常被当成引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。
function foo(obj) { with(obj){ a =5;
var m = 20; }
consloe.log(m); //20 } var obj = { a:1 } foo(obj); console.log(obj.a); //5
with可以将一个或多个对象的属性处理为完全隔离的作用域。但是在with块内var申明的变量不会局限在这个块级作用域,而是被添加到with所处的函数作用域中。
这两个机制的副作用:引擎无法在编译的时候对作用域查找优化,使用其中的任何一种机制都会使代码运行变慢。