读书人

各浏览器中对document.getElementById

发布时间: 2012-11-23 00:03:43 作者: rapoo

各浏览器中对document.getElementById等方法的实现差异

所有的Web前端同仁对 document.getElementById 都非常熟悉了。

开发过程中经常需要用其获取页面id为xx的元素,自从元老级js库Prototype流行后,都喜欢这么简写它

// 方式1function $(id){ return document.getElementById(id); }

?

有没有人想过为什么要这么写,而不用下面的方式写呢?

// 方式2var $ = document.getElementById;

这么写的$更简洁啊,也很明了,将document的方法getElementById赋值给变量$,用$去获取页面id为xx的元素。
实际上方式2在IE中是可行的(暂且这么说,IE9中有些变动),Firefox/Safari/Chrome/Opera则行不通。还请自行测试。
为什么Firefox/Safari/Chrome/Opera?方式2获取就不行呢,原因是这些浏览器中getElementById方法内部实现中需依赖this(document),IE则不需要this。或者说方式2在Firefox/Safari/Chrome/Opera中调用时说丢失了this,以下是个简单示例
// 定义一个函数showfunction show(){alert(this.name);}// 定义一个p对象,有name属性var p = {name:'Jack'};show.call(p); // -> 'Jack'show(); // -> ''show.call(null); // -> ''

可以看到show的实现中依赖this(简单说方法体中使用了this),因此调用时的环境(执行上下文)如果没有name属性,则得不到期望的结果。换句话说,IE引擎实现document.getElementById时没有用到this,而非IE浏览器 (Firefox/Safari/Chrome/Opera)需要用到this,这里的this正是document对象。直接调用方式2时内部的 this却是window对象,所以造成方式2在Firefox/Safari/Chrome/Opera不能根据id来正常获取元素。如果将document.getElementById的 执行环境换成了document而非window,则可以正常的使用$了。如下:??
// 修复document.getElementByIddocument.getElementById = (function(fn){    return function(){         return fn.apply(document,arguments);    };})(document.getElementById);// 修复后赋值给$,$可正常使用了var $ = document.getElementById;
?上面说到IE9有些变动。的确,IE9的情形和Firefox/Safari/Chrome/Opera是一样的,使用方式2将获取不了元素。
再次,ECMAScript5 中为function新增的 bind 方法可以实现同样的效果
// 方式3var $ = document.getElementById.bind(document);

?目前方式3只在IE9和Chrome中支持。(测试用的是IE9 pre4和Chrome7.0.503.0 dev)
分析了document.getElementById的情况,下面的一些方法就很好明白了
var prinf = document.write;prinf('<h3>Test prinf</h3>'); // IE6/7/8可运行,其它浏览器报错var prinfln = document.writeln;prinfln('<h3>Test prinfln</h3>'); // IE6/7/8可运行,其它浏览器报错var reload = location.reload;reload(); // IE6/7/8可运行,其它浏览器报错var go = history.go; go(-2); // IE6/7/8可运行,其它浏览器报错
??

?

1 楼 L--A--N--G 2010-09-28 牛。拜读了

读书人网 >Web前端

热点推荐