各浏览器对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 相关文章推荐
js 自动播放的实例代码
Nov 19 Javascript
JQuery 在线引用及测试引用是否成功
Jun 24 Javascript
js操作css属性实现div层展开关闭效果的方法
May 11 Javascript
Jquery简单实现GridView行高亮的方法
Jun 15 Javascript
JavaScript实现把数字转换成中文
Jun 29 Javascript
jQuery-1.9.1源码分析系列(十)事件系统之事件体系结构
Nov 19 Javascript
详解用原生JavaScript实现jQuery的某些简单功能
Dec 19 Javascript
微信小程序仿美团城市选择
Jun 06 Javascript
微信小程序中使用ECharts 异步加载数据实现图表功能
Jul 13 Javascript
浅谈vue后台管理系统权限控制思考与实践
Dec 19 Javascript
Angular8 实现table表格表头固定效果
Jan 03 Javascript
vue路由实现登录拦截
Mar 24 Vue.js
给事件响应函数传参数的四种方式小结
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 getimagesize 上传图片的长度和宽度检测代码
2010/05/15 PHP
php利用新浪接口查询ip获取地理位置示例
2014/01/20 PHP
Thinkphp模板标签if和eq的区别和比较实例分析
2015/07/01 PHP
php给图片添加文字水印方法汇总
2015/08/27 PHP
深入分析PHP优化及注意事项
2016/07/04 PHP
Zend Framework教程之Zend_Helpers动作助手ViewRenderer用法详解
2016/07/20 PHP
javascript Base类 包含基本的方法
2009/07/22 Javascript
event.srcElement 用法笔记e.target
2009/12/18 Javascript
对JavaScript中this指针的新理解分享
2015/01/31 Javascript
jQuery表单域选择器用法分析
2015/02/10 Javascript
百度地图给map添加右键菜单(判断是否为marker)
2016/03/04 Javascript
JavaScript获取图片像素颜色并转换为box-shadow显示
2016/03/11 Javascript
Boostrap实现的登录界面实例代码
2016/10/09 Javascript
easyui form validate总是返回false的原因及解决方法
2016/11/07 Javascript
JavaScript触发onScroll事件的函数节流详解
2016/12/14 Javascript
你有必要知道的10个JavaScript难点
2017/07/25 Javascript
ajax前台后台跨域请求处理方式
2018/02/08 Javascript
JS变量提升原理与用法实例浅析
2020/05/22 Javascript
vue 实现根据data中的属性值来设置不同的样式
2020/08/04 Javascript
antd 表格列宽自适应方法以及错误处理操作
2020/10/27 Javascript
[05:46]2018完美盛典-《同梦共竞》
2018/12/17 DOTA
基于循环神经网络(RNN)的古诗生成器
2018/03/26 Python
python opencv实现切变换 不裁减图片
2018/07/26 Python
python将txt文件读入为np.array的方法
2018/10/30 Python
Python 确定多项式拟合/回归的阶数实例
2018/12/29 Python
python-Web-flask-视图内容和模板知识点西宁街
2019/08/23 Python
python 对任意数据和曲线进行拟合并求出函数表达式的三种解决方案
2020/02/18 Python
基于CSS3实现的漂亮Menu菜单效果代码
2015/09/10 HTML / CSS
bareMinerals官网:矿物质化妆品和护肤品
2018/02/04 全球购物
英国名牌服装购物网站:OD’s Designer
2019/09/02 全球购物
料理师求职信
2014/01/30 职场文书
代领毕业证委托书
2014/08/02 职场文书
员工试用期自我鉴定范文
2014/09/15 职场文书
教师节横幅标语
2014/10/08 职场文书
vue中使用mockjs配置和使用方式
2022/04/06 Vue.js
Vue.Draggable实现交换位置
2022/04/07 Vue.js