with--废弃的语法

295 阅读2分钟

概念:

with的初衷是为了避免冗余的对象调用,

它的作用是将代码的作用域设置到一个特定的对象中。

它的目的主要是为了简化多次编写同一个对象的工作。

var qs = location.search.substring(1); 
var hostName = location.hostname; 
var url = location.href; 
// 上面几行代码都包含 location 对象。
如果使用 with 语句,可以把上面的代码改写成如下所示:
with(location){     
	var qs = search.substring(1);
    var hostName = hostname;
    var url = href; 
    }
在这个重写后的例子中,使用 with 语句关联了 location 对象。
这意味着在 with 语句的代码块 内部,每个变量首先被认为是一个局部变量,
而如果在局部环境中找不到该变量的定义,
就会查询 location 对象中是否有同名的属性。
如果发现了同名属性,则以 location 对象属性的值作为变量的值。

在《JavaScript权威指南》(第五版, David Flanagan, P109)给出了指出:

with语法用于暂时修改作用域链,他能够将Object添加到作用域头部,然后执行statement语句,再把作用域链恢复到原始状态

with (Object)
statement

那么使用with会出现什么问题呢?(问题的根源还是来源于作用域链的改变)

1:性能问题:

是否使用with,性能上有特别明显的差异。

2:不可预测性:

function foo(a){
    with(a){
        console.log(a);
    }
}
foo("sword");       // "sword"
foo({});            // Object {}
foo({a: "sword"});  // "sword"

在这个例子中,字符串和对象都没问题,
可是当传入带有a属性的对象时,就获取这个对象中的a属性了,
跟我们所预计的结果不一致

3:在with语句中声明的变量,并不属于with指定的参数对象:

var a ={};   
with(a){
    x = 'sword'
    var y = 'wang';
}
console.log(a.x);       // undefined
console.log(a.y);       // undefined
console.log(window.x);  // "sword"
console.log(window.y);  // "wang"	

在这个例子中with声明的变量实际上是被添加到外层的function中的

仅仅通过标识符及其上下文,无法确定一个with中的标识符指向什么,这是with被废弃的真正原因。它强行混乱了上下文使得程序的预测和解析变得困难。

参考文章:swordair.com/javascript-… 参考书籍:《JavaScript高级程序设计》(第3版, Nicholas C.Zakas, P60)