为什么不使用 javascript with?

众所周知大家对 with 都没什么好感,而且不推荐使用。

可以收集到的理由有:

下面几条来自 《javascript权威指南》 第 5 版本。

  1:使用with的语句很难优化。
  2:使用with语句速度要比不使用with语句的等价代码的速度慢得多。
  3:在with语句中的函数定义和变量初始化可能产生令人惊讶,和直觉相抵触的行为。
  4:90%(或者更高比例)的with应用场景都可以用其他更好的方式代替。

如何证明以上观点。

  第1点:貌似没有什么好的代码实例。(欢迎大家提供)

  第2点:使用with语句速度要比不使用with语句的等价代码的速度慢得多。

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次的运算估计也很少遇到,大家自己权衡。

 

  第3点:在with语句中的函数定义和变量初始化可能产生令人惊讶,和直觉相抵触的行为。

  

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();

看到 javascript 第6版上的例子:(一个更加悲剧的with使用)

var c ={};
        
        with(c){
            x = 111;
        }

        console.log(c.x); // undefined
        console.log(window.x); // 111

 

 

  第4点:90%(或者更高比例)的with应用场景都可以用其他更好的方式代替。

  可以想象with是帮你保存一个this指针而不用重复书写,我们当然也可以用一个变量来保存这个指针。

  故大部分with的应用场景可以有替代方案是可以做到的。

为什么做这个测试?

  只是想弄的明白些,或者接收更多人的看法。

posted @ 2012-12-03 11:49  Jun.lu  阅读(5155)  评论(3编辑  收藏