with语句的语法如下:
和()
with 会将计算出的对象添加到当前执行上下文的作用域链前面,然后使用这个扩展的作用域链来执行语句,最后恢复作用域链。 无论其中的语句是否正常退出,作用域链都会被恢复。
因为 with 会在作用域链的前面添加额外的对象,所以使用 with 可能会影响性能并导致难以发现的错误。 由于附加对象位于作用域链的前面,因此当执行 with 语句并且需要评估标识符时,将首先沿着对象链进行搜索。 如果找不到,则会依次查找作用域链中的原始对象。 因此,如果在with语句中频繁引用不在附加对象链中的变量,搜索速度会比不使用with时慢,例如:
(){ this.a="A"; } (){ this.b="B"; } B.=newA(); (){ this.c="C"; C.=newB(); ((){ ="";alert();//"" vara=1; =newC(); with(obj){alert();//""alert(myVar);//搜索速度比较慢}alert();//"" })();
上面的代码中,首先是通过方法来实现继承的。 在with语句中,执行alert(a)时需要找到变量a。 由于obj位于作用域链的最前面,并且obj中还有一个名为a的属性,因此找到了obj中的a。 执行alert(myVar)需要搜索变量myVal,而obj中没有名为myVal的属性。 它会继续在作用域链中搜索后续对象,因此使用with比不使用with慢。 需要注意的是,最后一条语句alert(a)并不在with中,所以找到的a是之前声明类型的变量。
使用with语句可以快速访问对象的属性。 然而,结果有时可能是不可预测的,所以你应该避免使用它。 例如:
与(对象){ a=b; }
上面的代码与下面的代码完成了相同的事情。
if(obj.a===){ a=obj.b====?b:obj.b; }else{ .a=obj.b====?b:obj.b; }
因此,前面的代码等效于以下任何语句。
a=b; a=obj.b; obj.a=b; .a=obj.b;
通过阅读代码无法直接判断您得到的是哪一条语句。 a和b可能会随着程序运行到下一步而改变,甚至在程序运行过程中也会改变。 如果我们无法阅读程序来理解它会做什么,我们就不能确信它会正确执行我们要求它执行的操作。
语言中 with 语句的存在严重影响了处理器速度,因为它阻止了变量名的词法作用域绑定。 这是出于好意,但如果没有它,语言可能会更好。