LHS(Left-Hand Side):通过作用域找到变量容器——获取值
RHS(Right-Hand Side):从容器中获取值——引用
eval() 修改作用域 已经启用
说明:解释字符串,在当前作用域执行其中js代码
思想:在运行期间修改书写时候的作用域
场景:eval()一般用于执行动态创建的代码
亲戚:setTimeout(..)、setInterval(..) 的第一个参数传入动态代码,但不建议使用
不建议使用:使用动态代码性能消极大,此功能可替代
// 代码说明
var b = 2;
function foo(str, a){
//相当于根据参数,临时修改了函数,修改了作用域
eval(str); //传入的字符串代码在这里执行
console.log(a, b)
}
foo("var b = 3;", 1) // 1 3
with函数 修改作用域
MDN说明: 扩展一个语(对象)的作用域链
其他说明: 为一个或一组语句指定默认对象
场景: with 重复引用同一个对象中的个属性的快捷方式
相对于eval:with 是创建性的作用域,而不是现有的修改
不建议使用:性能消耗大,修改了书写时候的作用域容易造成作用域混乱
严格模式下禁用
// 例子
var A = {a: 1, b: 2, c: 3}
with(A){//扩展A的作用域
//在该作用域 中执行代码
a = 4;
b = 5;
}
console.log(A) // {a: 4, b: 5,c: 3}
// 等价于:
// A.a = 4;
// A.b = 5;
with内部是LHS引用:当变量不存在的时候讲将声明一个全局变量
var o1 = {a: 3},
o2 = {b: 3};
function foo(obj){ // 修改对象的a属性 方法
with(obj){
a = 2; // 引用参数对象的a并赋值为 2
}
console.log(obj); //修改后打印出
}
foo(o1); // {a:2} 修改成功
foo(o2); // {b: 3} 没有a 属性,也没有添加
// with函数:LHS查找 o2的作用域 的a属性, 没找到
// 隐式创建了 全局的 a 变量并赋值 2
console.log(a) // 2 a全局变量被创建
LHS引用隐式创建全局变量
说明:在函数内部,引用变量,当不存在时自动创建一个全局变量
var a = 2;
function fn(a){
// b 并没有明个去声明
b = a; //此方法在严格模式下会报错
}
fn(a); // 调用一下
console.log(b); // 2 在全局中可以打印出b 尽管没有明确声明
关于修改作用域的性能
原因:JS引擎在编译阶段会对词法作用域进行静态分析,以便在执行时快速找到识别符。
但:当遇到eval 和 with 时候,由于无法确定作用域的具体修改,并不能有效的优化。