所有Web前端同仁对 document.getElementById 都非常熟悉了。开发过程中经常需要用其获取页面id为xx的元素,自从元老级JS库Prototype流行后,都喜欢这么简写它
  
    
      
        view sourceprint?
      
    
    
      
        
      
      
        
          
            
              | 
                2
               | 
              
                function $(id){ return document.getElementById(id); }
               | 
            
          
        
      
    
  
  有没有人想过为什么要这么写,而不用下面的方式写呢?
  
    
      
        view sourceprint?
      
    
    
      
        
      
      
        
          
            
              | 
                2
               | 
              
                var $ = document.getElementById;
               | 
            
          
        
      
    
  
  这么写的$更简洁啊,也很明了,将document的方法getElementById赋值给变量$,用$去获取页面id为xx的元素。实际上方式2在IE6/7/8中是可行的(IE9中有些变动),Firefox/Safari/Chrome/Opera则行不通。还请自行测试。
  
  为什么Firefox/Safari/Chrome/Opera 方式2获取就不行呢,原因是这些浏览器中getElementById方法内部实现中需依赖this(document),IE则不需要this。或者说方式2在Firefox/Safari/Chrome/Opera中调用时说丢失了this,以下是个简单示例
  
    
      
        view sourceprint?
      
    
    
      
        
      
      
        
          
            
              | 
                2
               | 
              
                function show(){alert(this.name);}
               | 
            
          
        
      
      
        
      
      
        
      
      
        
      
      
        
      
      
        
          
            
              | 
                7
               | 
              
                show.call(p); // -> 'Jack'
               | 
            
          
        
      
      
        
      
      
        
          
            
              | 
                9
               | 
              
                show.call(null); // -> ''<BR>
               | 
            
          
        
      
    
  
  可以看到show的实现中依赖this(简单说方法体中使用了this),因此调用时的环境(执行上下文)如果没有name属性,则得不到期望的结果。
  换句话说,IE6/7/8实现document.getElementById时没有用到this,而 IE9/Firefox/Safari/Chrome/Opera 需要用到this,这里的this正是document对象。直接调用方式2时内部的 this却是window对象,所以造成方式2在 Firefox/Safari/Chrome/Opera 不能根据id来正常获取元素。
  
  如果将document.getElementById的 执行环境换成了document而非window,则可以正常的使用$了。如下
  
    
      
        view sourceprint?
      
    
    
      
        
          
            
              | 
                1
               | 
              
                // 修复document.getElementById
               | 
            
          
        
      
      
        
          
            
              | 
                2
               | 
              
                document.getElementById = (function(fn){
               | 
            
          
        
      
      
        
      
      
        
          
            
              | 
                4
               | 
              
                        return fn.apply(document,arguments);
               | 
            
          
        
      
      
        
      
      
        
          
            
              | 
                6
               | 
              
                })(document.getElementById);
               | 
            
          
        
      
      
        
      
      
        
      
      
        
          
            
              | 
                9
               | 
              
                var $ = document.getElementById;
               | 
            
          
        
      
    
  
  
  再次,ECMAScript5 中为function新增的 bind 方法可以实现同样的效果
  
    
      
        view sourceprint?
      
    
    
      
        
      
      
        
          
            
              | 
                2
               | 
              
                var $ = document.getElementById.bind(document);
               | 
            
          
        
      
    
  
  但目前方式3只有IE9/Firefox/Chrome/支持。
  
  分析了getElementById的情况,下面的一些方法在各浏览器中的差异原因就很好明白了
  
    
      
        view sourceprint?
      
    
    
      
        
          
            
              | 
                01
               | 
              
                var prinf = document.write;
               | 
            
          
        
      
      
        
          
            
              | 
                02
               | 
              
                prinf('<h3>Test prinf</h3>'); // IE6/7/8可运行,其它浏览器报错
               | 
            
          
        
      
      
        
      
      
        
          
            
              | 
                04
               | 
              
                var prinfln = document.writeln;
               | 
            
          
        
      
      
        
          
            
              | 
                05
               | 
              
                prinfln('<h3>Test prinfln</h3>'); // IE6/7/8可运行,其它浏览器报错
               | 
            
          
        
      
      
        
      
      
        
          
            
              | 
                07
               | 
              
                var reload = location.reload;
               | 
            
          
        
      
      
        
          
            
              | 
                08
               | 
              
                reload(); // IE6/7/8可运行,其它浏览器报错
               | 
            
          
        
      
      
        
      
      
        
      
      
        
          
            
              | 
                11
               | 
              
                go(-2); // IE6/7/8可运行,其它浏览器报错
               |