各浏览器对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 getBoundingClientRect() 来获取页面元素的位置
Nov 25 Javascript
谈谈关于JavaScript 中的 MVC 模式
Apr 11 Javascript
用JS在浏览器中创建下载文件
Mar 05 Javascript
邮箱下拉自动填充选择示例代码附图
Apr 03 Javascript
jQuery 删除或是清空某个HTML元素示例
Aug 04 Javascript
JavaScript中实现PHP的打乱数组函数shuffle实例
Oct 11 Javascript
原生js编写焦点图效果
Dec 08 Javascript
浅谈Vue.js
Mar 02 Javascript
整理关于Bootstrap模态弹出框的慕课笔记
Mar 29 Javascript
vue2.0构建单页应用最佳实战
Apr 01 Javascript
利用vue+elementUI实现部分引入组件的方法详解
Nov 22 Javascript
React Router V4使用指南(精讲)
Sep 17 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
一个连接两个不同MYSQL数据库的PHP程序
2006/10/09 PHP
深入file_get_contents与curl函数的详解
2013/06/25 PHP
PHP面向对象程序设计OOP继承用法入门示例
2016/12/27 PHP
利用PHP访问带有密码的Redis方法示例
2017/02/09 PHP
javascript跟随滚动效果插件代码(javascript Follow Plugin)
2013/08/03 Javascript
Javascript基础知识(二)事件
2014/09/29 Javascript
jquery中ajax使用error调试错误的方法
2015/02/08 Javascript
js实现文本框选中的方法
2015/05/26 Javascript
js文本框走动跑马灯效果代码分享
2015/08/25 Javascript
jQuery监听浏览器窗口大小的变化实例
2017/02/07 Javascript
AngularJS表单验证功能
2017/10/19 Javascript
JS实现计算小于非负数n的素数的数量算法示例
2019/02/26 Javascript
vue-cli3 项目优化之通过 node 自动生成组件模板 generate View、Component
2019/04/30 Javascript
js图数据结构处理 迪杰斯特拉算法代码实例
2019/09/11 Javascript
vue中echarts引入中国地图的案例
2020/07/28 Javascript
antd 表格列宽自适应方法以及错误处理操作
2020/10/27 Javascript
vue 避免变量赋值后双向绑定的操作
2020/11/07 Javascript
[00:37]2016完美“圣”典风云人物:AMS宣传片
2016/12/06 DOTA
python远程登录代码
2008/04/29 Python
Python中if __name__ == &quot;__main__&quot;详细解释
2014/10/21 Python
Python求解平方根的方法
2015/03/11 Python
Python中用format函数格式化字符串的用法
2015/04/08 Python
python 系统调用的实例详解
2017/07/11 Python
python中的文件打开与关闭操作命令介绍
2018/04/26 Python
使用Pycharm分段执行代码
2020/04/15 Python
matplotlib之pyplot模块坐标轴标签设置使用(xlabel()、ylabel())
2021/02/22 Python
一些Unix笔试题和面试题
2013/01/22 面试题
受伤赔偿协议书
2014/09/24 职场文书
2014年教学管理工作总结
2014/12/02 职场文书
2015年幼儿园元旦亲子活动方案
2014/12/09 职场文书
春节慰问信范文
2015/02/15 职场文书
2015年数学教师工作总结
2015/05/20 职场文书
2015年度绩效考核工作总结
2015/05/27 职场文书
2016年入党心得体会范文
2016/01/23 职场文书
市语委办2016年第十九届“推普周”活动总结
2016/04/05 职场文书
标准发言稿结尾
2019/07/18 职场文书