作用域中LHS查询和RHS查询
LHS查询:赋值操作左侧的查询,LHS查询试图找到变量的容器本身,,从而对其赋值。
RHS查询:赋值操作右侧的查询,可以理解为“取到某某的值”
举例:
考虑以下代码:
console.log( a );
其中对a的引用是一个RHS引用,因为这里a并没有赋予任何值。相应地,需要查找并取得a的值,这样才能将值传递给console.log(..)。
相比之下,例如:
a = 2;
这里对a的引用则是LHS引用,因为实际上我们并不关心当前的值是什么,只是想要为= 2这个赋值操作找到一个目标。
function foo(a) {
console.log(a);
}
foo(2);
RHS查询有:
- foo(..), 查询foo函数
- 函数内Console对象的查询
- 对a进行RHS查询
LHS查询:
- 把2赋值给参数a时,对a进行LHS查询;
- 区别
如果RHS查询在所有嵌套的作用域中找不到所需的变量,引擎就会抛出ReferenceError异常;
相比之下,非严格模式下,当执行LHS查询时,如果在顶层作用域也无法找到目标变量,全局作用域会创建一个具有该名称的变量,并将其返回给引擎;严格模式下,LHS查询,找不到目标变量时也会抛出ReferenceError异常。
如果RHS查询找到了一个变量,但是对这个变量的值进行不合理的操作(如试着引用null类型的属性),引擎会抛出TypeError异常。
- 作用域
作用域是一套规则,用来管理引擎如何在当前作用
域以及嵌套的子作用域中根据标识符名称进行变量查找。如果查找的目的是对
变量进行赋值,那么就会使用 LHS 查询;如果目的是获取变量的值,就会使用 RHS 查询。
function foo(obj) {
with (obj) {
a = 2;
}
}
var o1 = {
a: 3
};
var o2 = {
b: 3
};
foo( o1 );
console.log( o1.a ); // 2
foo( o2 );
console.log( o2.a ); // undefined
console.log( a ); // 2——不好,a被泄漏到全局作用域上了!
with可以将一个没有或有多个属性的对象处理为一个完全隔离的词法作用域,因此这个对象的属性也会被处理为定义在这个作用域中的词法标识符。
eval与with的区别:eval(..)函数如果接受了含有一个或多个声明的代码,就会修改其所处的词法作用域,而with声明实际上是根据你传递给它的对象凭空创建了一个全新的词法作用域。