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


Posted in Javascript onDecember 05, 2013

所有Web前端同仁对 document.getElementById 都非常熟悉了。开发过程中经常需要用其获取页面id为xx的元素,自从元老级JS库Prototype流行后,都喜欢这么简写它

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

有没有人想过为什么要这么写,而不用下面的方式写呢?
// 方式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,以下是个简单示例

// 定义一个函数show 
function show(){alert(this.name);} // 定义一个p对象,有name属性 
var p = {name:'Jack'}; 
show.call(p); // -> 'Jack' 
show(); // -> '' 
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,则可以正常的使用$了。如下

// 修复document.getElementById 
document.getElementById = (function(fn){ 
    return function(){  
        return fn.apply(document,arguments); 
    }; 
})(document.getElementById); // 修复后赋值给$,$可正常使用了 
var $ = document.getElementById;

再次,ECMAScript5 中为function新增的 bind 方法可以实现同样的效果
// 方式3 
var $ = document.getElementById.bind(document);

但目前方式3只有IE9/Firefox/Chrome/支持。

分析了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可运行,其它浏览器报错
Javascript 相关文章推荐
短信提示使用 特效
Jan 19 Javascript
js 多浏览器分别判断代码
Apr 01 Javascript
JS中for循序中延迟加载动态效果的具体实现
Aug 18 Javascript
JS数组去重与取重的示例代码
Jan 24 Javascript
回车直接实现点击某按钮的效果即触发单击事件
Feb 27 Javascript
js+canvas绘制五角星的方法
Jan 28 Javascript
jstree单选功能的实现方法
Jun 07 Javascript
vue-cli脚手架build目录下utils.js工具配置文件详解
Sep 14 Javascript
JS实现计算小于非负数n的素数的数量算法示例
Feb 26 Javascript
vue webpack重写cookie路径的方法
Jul 10 Javascript
layui 数据表格+分页+搜索+checkbox+缓存选中项数据的方法
Sep 21 Javascript
js实现点击选项置顶动画效果
Aug 25 Javascript
给事件响应函数传参数的四种方式小结
Dec 05 #Javascript
弹出最简单的模式化遮罩层的js代码
Dec 04 #Javascript
js如何设置在iframe框架中指定div不显示
Dec 04 #Javascript
jquery动态改变onclick属性导致失效的问题解决方法
Dec 04 #Javascript
javascript设置金额样式转换保留两位小数示例代码
Dec 04 #Javascript
下拉列表select 由左边框移动到右边示例
Dec 04 #Javascript
JS获得QQ号码的昵称,头像,生日的简单实例
Dec 04 #Javascript
You might like
PHP在XP下IIS和Apache2服务器上的安装
2006/09/05 PHP
使用adodb lite解决问题
2006/12/31 PHP
PHP Class&amp;Object -- PHP 自排序二叉树的深入解析
2013/06/25 PHP
phplist及phpmailer(组合使用)通过gmail发送邮件的配置方法
2016/03/30 PHP
php基于curl重写file_get_contents函数实例
2016/11/08 PHP
PHP使用Redis实现防止大并发下二次写入的方法
2017/10/09 PHP
Html中JS脚本执行顺序简单举例说明
2010/06/19 Javascript
麻雀虽小五脏俱全 Dojo自定义控件应用
2010/09/04 Javascript
js setTimeout 常见问题小结
2013/08/13 Javascript
全面理解面向对象的 JavaScript(来自ibm)
2013/11/10 Javascript
JavaScript实现三阶幻方算法谜题解答
2014/12/29 Javascript
jQuery实现带分组数据的Table表头排序实例分析
2015/11/24 Javascript
一道JS前端闭包面试题解析
2015/12/25 Javascript
jQuery实现div随意拖动的实例代码(通用代码)
2016/01/28 Javascript
Javascript的比较汇总
2016/07/25 Javascript
Vue.js自定义指令的用法与实例解析
2017/01/18 Javascript
JS简单封装的图片无缝滚动效果示例【测试可用】
2017/03/22 Javascript
Vue-router 中hash模式和history模式的区别
2018/07/24 Javascript
vue中动态添加class类名的方法
2018/09/05 Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
2019/06/19 jQuery
javascript事件循环event loop的简单模型解释与应用分析
2020/03/14 Javascript
vue 解决IOS10低版本白屏的问题
2020/11/17 Javascript
基于scrapy实现的简单蜘蛛采集程序
2015/04/17 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
2017/12/20 Python
python for 循环获取index索引的方法
2019/02/01 Python
python tqdm 实现滚动条不上下滚动代码(保持一行内滚动)
2020/02/19 Python
LTD Commodities:礼品,独特发现,家居装饰,家用器皿
2017/08/11 全球购物
户籍证明的格式
2014/01/13 职场文书
《夸父追日》教学反思
2014/02/26 职场文书
高考备战决心书
2014/03/11 职场文书
技校毕业生自荐书
2014/05/23 职场文书
市级青年文明号申报材料
2014/05/26 职场文书
幼师求职信
2014/06/23 职场文书
个人债务授权委托书
2014/10/17 职场文书
学术会议邀请函
2015/01/30 职场文书
博士给导师的自荐信
2015/03/06 职场文书