各浏览器对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页面刷新与弹出窗口问题的解决方法
Mar 02 Javascript
javascript获取元素离文档各边距离的方法
Feb 13 Javascript
JS动画效果打开、关闭层的实现方法
May 09 Javascript
jquery实现鼠标滑过显示二级下拉菜单效果
Aug 24 Javascript
js jquery获取当前元素的兄弟级 上一个 下一个元素
Sep 01 Javascript
javascript正则表达式定义(语法)总结
Jan 08 Javascript
深入学习js瀑布流布局
Oct 14 Javascript
使用BootStrap进行轮播图的制作
Jan 06 Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
Feb 09 Javascript
JS表格组件神器bootstrap table使用指南详解
Apr 12 Javascript
Node.js实现发送邮件功能
Nov 06 Javascript
VUE2.0中Jsonp的使用方法
May 22 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生成便于打印的网页
2006/10/09 PHP
PHP 递归效率分析
2009/11/24 PHP
IIS6.0 开启Gzip方法及PHP Gzip函数分享
2014/06/08 PHP
PHP实现加强版加密解密类实例
2015/07/29 PHP
laravel-admin 后台表格筛选设置默认的查询日期方法
2019/10/03 PHP
用htc组件制作windows选项卡
2007/01/13 Javascript
javascript圆盘抽奖程序实现原理和完整代码例子
2014/06/03 Javascript
在JavaScript中如何解决用execCommand(
2015/10/19 Javascript
Javascript自执行匿名函数(function() { })()的原理浅析
2016/05/15 Javascript
详解Vue学习笔记入门篇之组件的内容分发(slot)
2017/07/17 Javascript
纯js实现图片匀速淡入淡出效果
2017/08/22 Javascript
详解HTML5 使用video标签实现选择摄像头功能
2017/10/25 Javascript
原生JS实现ajax与ajax的跨域请求实例
2017/12/01 Javascript
VUE DOM加载后执行自定义事件的方法
2018/09/07 Javascript
详解在微信小程序的JS脚本中使用Promise来优化函数处理
2019/03/06 Javascript
webpack 代码分离优化快速指北
2019/05/18 Javascript
原生js实现无缝轮播图
2020/01/11 Javascript
vue下canvas裁剪图片实例讲解
2020/04/16 Javascript
[03:04]DOTA2英雄基础教程 影魔
2013/12/11 DOTA
python写的ARP攻击代码实例
2014/06/04 Python
Python中垃圾回收和del语句详解
2018/11/15 Python
对Python 语音识别框架详解
2018/12/24 Python
matplotlib 对坐标的控制,加图例注释的操作
2020/04/17 Python
Python 如何定义匿名或内联函数
2020/08/01 Python
css3实现wifi信号逐渐增强效果实例
2017/08/09 HTML / CSS
世界上最大的高分辨率在线图片库:Alamy
2018/07/07 全球购物
泰国王权免税店官方网站:KingPower
2019/03/11 全球购物
Mansur Gavriel官网:纽约市的一个设计品牌
2019/05/02 全球购物
中学生评语大全
2014/04/18 职场文书
《得道多助,失道寡助》教学反思
2014/04/19 职场文书
商场周年庆活动方案
2014/08/19 职场文书
学习张林森心得体会
2014/09/10 职场文书
四风问题专项整治工作情况报告
2014/10/28 职场文书
给客户的感谢信
2015/01/21 职场文书
英文邀请函
2015/02/02 职场文书
Golang 切片(Slice)实现增删改查
2022/04/22 Golang