各浏览器对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 相关文章推荐
javascript-简单的日历实现及Date对象语法介绍(附图)
May 30 Javascript
HTML,CSS,JavaScript速查表推荐
Dec 02 Javascript
JavaScript中利用Array和Object实现Map的方法
Jul 27 Javascript
JS+Canvas实现的俄罗斯方块游戏完整实例
Dec 12 Javascript
Vuex利用state保存新闻数据实例
Jun 28 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
Aug 03 Javascript
vue组件数据传递、父子组件数据获取,slot,router路由功能示例
Mar 19 Javascript
vue路由--网站导航功能详解
Mar 29 Javascript
基于jquery ajax的多文件上传进度条过程解析
Sep 11 jQuery
js数组相减简单示例【删除a数组所有与b数组相同元素】
Mar 04 Javascript
用VsCode编辑TypeScript的实现方法
May 07 Javascript
微信小程序实现聊天室
Aug 21 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
德劲1103的维修打理经验
2021/03/02 无线电
php 无限级数据JSON格式及JS解析
2010/07/17 PHP
php使用curl出现Expect:100-continue解决方法
2015/03/03 PHP
浅谈PHP中foreach/in_array的使用
2015/11/02 PHP
php无限分类使用concat如何实现
2015/11/05 PHP
详解PHP中curl_multi并发的实现
2020/06/08 PHP
RR vs IO BO3 第一场2.13
2021/03/10 DOTA
jQuery+CSS 实现随滚动条增减的汽水瓶中的液体效果
2011/09/26 Javascript
Javascript实现关联数据(Linked Data)查询及注意细节
2013/02/22 Javascript
使用jquery局部刷新(jquery.load)从数据库取出数据
2014/01/22 Javascript
JavaScript里实用的原生API汇总
2015/05/14 Javascript
jquery实现表单验证并阻止非法提交
2015/07/09 Javascript
利用js获取下拉框中所选的值
2016/12/01 Javascript
easyui datebox 时间限制,datebox开始时间限制结束时间,datebox截止日期比起始日期大的实现代码
2017/01/12 Javascript
Nodejs+angularjs结合multiparty实现多图片上传的示例代码
2017/09/29 NodeJs
AngularJS中下拉框的高级用法示例
2017/10/11 Javascript
AngularJS表单验证功能
2017/10/19 Javascript
Vue项目中如何引入icon图标
2018/03/28 Javascript
jQuery 导航自动跟随滚动的实现代码
2018/05/30 jQuery
Vue项目中使用jsonp抓取跨域数据的方法
2019/11/10 Javascript
jQuery使用ajax传递json对象到服务端及contentType的用法示例
2020/03/12 jQuery
javascript前端实现多视频上传
2020/12/13 Javascript
Vue实现点击当前行变色
2020/12/14 Vue.js
跟老齐学Python之从if开始语句的征程
2014/09/14 Python
Python切片操作深入详解
2018/07/27 Python
基于Django的乐观锁与悲观锁解决订单并发问题详解
2019/07/31 Python
PyTorch在Windows环境搭建的方法步骤
2020/05/12 Python
Python中的xlrd模块使用原理解析
2020/05/21 Python
css3 给页面加个半圆形导航条主要利用旋转和倾斜样式
2014/02/10 HTML / CSS
香港个人化生活购物网站:Ballyhoo Limited
2016/09/10 全球购物
美国第一香水网站:Perfume.com
2017/01/23 全球购物
当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
2014/09/09 面试题
什么是Rollback Segment
2013/04/22 面试题
团队队名口号大全
2014/06/06 职场文书
五年级语文教学反思
2016/03/03 职场文书
《英雄联盟》2022日蚀、月蚀皮肤演示 黑潮亚索曝光
2022/04/13 其他游戏