为什么不使用 javascript with?
by Jun.lu
at 2012-12-03 11:49:00
original http://www.cnblogs.com/idche/archive/2012/12/03/2799355.html
众所周知大家对 with 都没什么好感,而且不推荐使用。
可以收集到的理由有:
下面几条来自 《javascript权威指南》 第 5 版本。
1:使用with的语句很难优化。
2:使用with语句速度要比不使用with语句的等价代码的速度慢得多。
3:在with语句中的函数定义和变量初始化可能产生令人惊讶,和直觉相抵触的行为。
4:90%(或者更高比例)的with应用场景都可以用其他更好的方式代替。
如何证明以上观点。
第一点貌似没有什么好的代码实例。(欢迎大家提供)
第2点:
var a = {
a:{
a:{
a:{
a:{
a:{
a:{
b:1
}
}
}
}
}
}
};
//取值与赋值 10000
function noWith(){
var obj = a.a.a.a.a.a.a, i=100000, j = 0;
for(; i; i--){
j = obj.b;
obj.b = i;
}
}
//取值与赋值 10000
function yesWith(){
var i=100000, j = 0;
with( a.a.a.a.a.a.a ){
for(; i; i--){
j = b;
b = i;
}
}
}
var t = new Date().getTime();
//noWith();
yesWith();
console.log(new Date().getTime() - t);
//运行上面两个函数, 对一个比较深的对象取值与赋值 100000 次
//不使用with: 0-3毫秒(chrome浏览器,可能是V8太NB,我自己都不信了),换了Firefox 大约是7-10毫秒
//使用with: 120-130毫秒之间(chrome), 110-120毫秒(Firefox)
//结论:使用with进行大量运算确实存在一些性能问题,但是10W次的运算估计也很少遇到,大家自己权衡。
a:{
a:{
a:{
a:{
a:{
a:{
b:1
}
}
}
}
}
}
};
//取值与赋值 10000
function noWith(){
var obj = a.a.a.a.a.a.a, i=100000, j = 0;
for(; i; i--){
j = obj.b;
obj.b = i;
}
}
//取值与赋值 10000
function yesWith(){
var i=100000, j = 0;
with( a.a.a.a.a.a.a ){
for(; i; i--){
j = b;
b = i;
}
}
}
var t = new Date().getTime();
//noWith();
yesWith();
console.log(new Date().getTime() - t);
//运行上面两个函数, 对一个比较深的对象取值与赋值 100000 次
//不使用with: 0-3毫秒(chrome浏览器,可能是V8太NB,我自己都不信了),换了Firefox 大约是7-10毫秒
//使用with: 120-130毫秒之间(chrome), 110-120毫秒(Firefox)
//结论:使用with进行大量运算确实存在一些性能问题,但是10W次的运算估计也很少遇到,大家自己权衡。
第3点:
function useWith(){
var obj = {
item:{//姑且把这个对象叫做 this1
key:1
}
};
with( obj.item ){
obj.item = {
key : 2
};
console.log( key ); //1, 你悲剧的访问到了1
//理由:with 已经确定了当前 this 指向了 this1,
//在访问 key 的时候不会重新读取 obj.item 新的指针。
//疑问:本来在 obj.item 被重新赋值的时候就应该把 this1 的这个对象抛弃了(它已经没有存在引用了),那么最后一句key的访问结束内存会被回收吗?
}
}
useWith();
var obj = {
item:{//姑且把这个对象叫做 this1
key:1
}
};
with( obj.item ){
obj.item = {
key : 2
};
console.log( key ); //1, 你悲剧的访问到了1
//理由:with 已经确定了当前 this 指向了 this1,
//在访问 key 的时候不会重新读取 obj.item 新的指针。
//疑问:本来在 obj.item 被重新赋值的时候就应该把 this1 的这个对象抛弃了(它已经没有存在引用了),那么最后一句key的访问结束内存会被回收吗?
}
}
useWith();
看到 javascript 第6版上的例子:(一个更加悲剧的with使用)
var c ={};
with(c){
x = 111;
}
console.log(c.x); // undefined
console.log(window.x); // 111
with(c){
x = 111;
}
console.log(c.x); // undefined
console.log(window.x); // 111
第4点:
可以想象with是帮你保存一个this指针而不用重复书写,我们当然也可以用一个变量来保存这个指针。
故大部分with的应用场景可以有替代方案是可以做到的。
为什么做这个测试?
只是想弄的明白些,或者接收更多人的看法。