各浏览器对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 相关文章推荐
flash+jQuery实现可关闭及重复播放的压顶广告
Apr 15 Javascript
使用Javascript监控前端相关数据的代码
Oct 27 Javascript
Javascript实现base64的加密解密方法示例
Jun 27 Javascript
Angular.js自动化测试之protractor详解
Jul 07 Javascript
angular内置provider之$compileProvider详解
Sep 27 Javascript
jQuery ajax读取本地json文件的实例
Oct 31 jQuery
js断点调试经验分享
Dec 08 Javascript
详解ES6语法之可迭代协议和迭代器协议
Jan 13 Javascript
React中使用async validator进行表单验证的实例代码
Aug 17 Javascript
jQuery中each和js中forEach的区别分析
Feb 27 jQuery
layui 富文本编辑器和textarea值的相互传递方法
Sep 18 Javascript
jquery制作的移动端购物车效果完整示例
Feb 24 jQuery
给事件响应函数传参数的四种方式小结
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
DC动漫人物排行
2020/03/03 欧美动漫
虫族 Zerg 历史背景
2020/03/14 星际争霸
ThinkPHP整合百度Ueditor图文教程
2014/10/21 PHP
php字符比较函数similar_text、strnatcmp与strcasecmp用法分析
2014/11/18 PHP
PHP数组与对象之间使用递归实现转换的方法
2015/06/24 PHP
Linux操作系统安装LAMP环境
2015/06/26 PHP
ucenter中词语过滤原理分析
2016/07/13 PHP
JQuery 无废话系列教程(二) jquery实战篇上
2009/06/23 Javascript
JS中confirm,alert,prompt函数使用区别分析
2010/04/01 Javascript
你必须知道的Javascript知识点之&quot;单线程事件驱动&quot;的使用
2013/04/23 Javascript
JS简单的轮播的图片滚动实例
2013/06/17 Javascript
firefox浏览器用jquery.uploadify插件上传时报HTTP 302错误
2015/03/01 Javascript
javascript转换静态图片,增加粒子动画效果
2015/05/28 Javascript
微信小程序 加载 app-service.js 错误解决方法
2016/10/12 Javascript
Bootstrap框架的学习教程详解(二)
2016/10/18 Javascript
webix+springmvc session超时跳转登录页面
2016/10/30 Javascript
详解js产生对象的3种基本方式(工厂模式,构造函数模式,原型模式)
2017/01/09 Javascript
js实现颜色阶梯渐变效果(Gradient算法)
2017/03/21 Javascript
jQuery实现文章图片弹出放大效果
2017/04/06 jQuery
JavaScript运动框架 解决防抖动问题、悬浮对联(二)
2017/05/17 Javascript
详解微信小程序 通过控制CSS实现view隐藏与显示
2017/05/24 Javascript
打字效果动画的4种实现方法(超简单)
2017/10/18 Javascript
使用vue制作滑动标签
2019/09/21 Javascript
python实现反转部分单向链表
2018/09/27 Python
pyqt5 删除layout中的所有widget方法
2019/06/25 Python
python实现接口并发测试脚本
2019/06/25 Python
基于python实现从尾到头打印链表
2019/11/02 Python
基于python的列表list和集合set操作
2019/11/24 Python
python字符串,元组,列表,字典互转代码实例详解
2020/02/14 Python
Python编写单元测试代码实例
2020/09/10 Python
Linux常见面试题
2016/10/04 面试题
班组长安全生产职责
2013/12/16 职场文书
代办委托书怎么写
2014/08/01 职场文书
计划生育工作汇报
2014/10/28 职场文书
使用Springboot实现健身房管理系统
2021/07/01 Java/Android
mysql 获取相邻数据项
2022/05/11 MySQL