跨浏览器 JavaScript






4.65/5 (22投票s)
2005年12月15日
5分钟阅读

166313

1117
一个不为人知的技巧,可以通过实现一个小的兼容层来简化多浏览器编程。
引言
如果您需要实现一个大量使用 JavaScript 进行客户端效果或类似 AJAX 功能的 Web 应用程序,并且需要支持 Microsoft Internet Explorer 6.0 以上版本,那么您可能会在这里找到一个不为人知的技巧,通过实现一个小的兼容层来简化您的编程。
Microsoft Internet Explorer 和 Mozilla/FireFox 这两个浏览器都拥有根据 HTML、CSS 和 JavaScript 标准定义的许多功能,其中一些功能对于在客户端实现某些功能非常有用。由于这些不同平台提供了一些可扩展性功能,因此可以扩展一个浏览器,使其拥有开箱即用时不存在于另一个浏览器中的方法和属性。
JavaScript 原型
浏览器平台中包含的 JavaScript 语言解释器提供几乎相同的功能。实际上没有必要使用此功能来为其中一个平台提供一些缺失的功能,但它仍然是一个有趣的功能,并且可以为您提供扩展两个平台的可能性。
JavaScript 的对象类型,最好称之为 JavaScript 的内置对象(String
、Number
、Array
等),它们是 JavaScript 语言的一部分,通过使用可用的 prototype
属性具有可扩展性机制。
通过将新函数附加到 prototype
,您可以使该方法可用于所有派生自该类型的对象。
下面的示例向所有字符串对象添加了一个 trim()
方法,该方法可以删除所有前导和尾随空格,并返回一个包含剩余字符(如果有)的新字符串。
String.prototype.trim = function() {
return (this.replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, ""));
}
要使用此函数,您将使用以下语法
var s = " Hello World ";
var txt = s.trim(); // returns only "Hello World"
您可以在 Internet Explorer 和 Mozilla/FireFox 中使用此可扩展性功能来为内置对象添加新方法和(只读)属性,但没有跨浏览器的方法来捕获对这些对象属性的访问。
您可能会认为也可以添加一个全局方法 trim(s)
,它使用参数和返回值来执行相同操作,但这可能会与其他使用相同名称的库中的变量或方法发生冲突。您也可以向 Array
对象添加一个 trim
方法来处理数组项,而不会发生冲突。
有关 prototype
属性的一些一般信息可以在以下网址找到:MSDN。
Mozilla/FireFox 中的 JavaScript 原型
Mozilla/FireFox 平台还提供了一个专有但非常有用的扩展模型,允许在 JavaScript 内置对象上实现属性。我在这里添加了一个 weight
属性,它返回字符串字符代码的总和。
String.prototype.__defineGetter__("weight",
function () {
var w = 0;
for (var n = 0; n < this.length; n++)
w += this.charCodeAt(n);
return w;
}
);
您可以在任何字符串上使用此属性。
var s = "ABC";
var n = s.weight; // will return 198
记住:
__defineGetter__
和 __defineSetter__
是 Mozilla/FireFox 特有的功能,您可以在互联网上通过使用这些关键字在 Google 上搜索找到一些(仍然很少的)示例。
HTML 对象的原型
在使用 Microsoft Internet Explorer 时,JavaScript 对象和 HTML 对象是完全不同的对象类型,但对于 Mozilla/FireFox,这些对象共享一个通用的实现。因此,我们现在要看的功能仅在 Mozilla/FireFox 中可用。
例如,Internet Explorer 支持许多 HTML 对象(如 span
、div
、p
等)的 innerText
属性,该属性可用于安全地访问和设置 HTML 对象的文本。
相反,Mozilla/Firefox 使用较新的 DOM Level 3 标准的 textContent
属性来执行相同操作。
现在您可以使用 Mozilla/FireFox 的可扩展性功能在所有 HTML 对象上模拟 innerText
属性,并且可以消除 JavaScript 程序中所有条件脚本。
var isIE = (window.navigator.userAgent.indexOf("MSIE") > 0);
if (! isIE) {
HTMLElement.prototype.__defineGetter__("innerText",
function () { return(this.textContent); });
HTMLElement.prototype.__defineSetter__("innerText",
function (txt) { this.textContent = txt; });
}
您只需将此脚本包含在您常用的 JavaScript 包含文件中即可。
这里有一些更多可用的 Microsoft 特定功能包装器。
innerText |
获取和设置 HTML 节点的内部文本。 |
obj.children[] |
返回 obj.childNodes[] 集合。这不是一个完美的模拟,但可能有助于您的代码正常工作。 |
XMLDocument |
从内部文本返回一个 XMLDocument 对象,该文本应该是 XML。 |
attachEvent |
将事件处理程序附加到 HTML 对象。 |
detachEvent |
从 HTML 对象分离事件处理程序。 |
window.event |
返回实际正在执行的事件对象。 |
event.srcElement |
返回正在执行的事件的目标节点。 |
event.cancelBubble |
停止当前事件的传播。 |
event.returnValue |
设置当前事件的返回值。 |
xmlobj.selectSingleNode |
使用 XPath 表达式从 XML 元素返回单个节点。 |
xmlobj.text |
返回 XML 元素的内部文本。 |
结论
如果您曾经认为编写跨浏览器兼容的 JavaScript 很难,那么现在您有机会构建自己的兼容层,使您的脚本更具可读性且更易于维护,并摆脱散布在整个 Web 应用程序中的条件代码片段。
这种方法很有帮助,但并非最终解决方案。许多人(包括我自己)希望当前和即将推出的标准能够被所有浏览器实现。最好在多个平台上可用时使用这些功能。也有一些很好的专有 Microsoft Internet Explorer 功能的示例,它们非常有用,以至于 Mozilla/Firefox 也实现了它们。最流行的示例是 XMLHTTP
对象,它允许实现类似 AJAX 的跨浏览器实现。
有关浏览器兼容性提示的一些好读物 URL
- QuirksMode
- 将应用程序从 Internet Explorer 迁移到 Mozilla
- 好奇:本文档包含了很多关于如何实现跨浏览器兼容页面的重要提示,但它本身不是跨浏览器兼容的。IE 会显示一个空白页。请使用 Firefox 阅读!
- 一本关于此主题的书.
在实现启用 AJAX 的框架时,JavaScript 编码变得越来越重要。目前使用这种方法的 JavaScript 库不多,但一些较新的库会这样做。这里有一些链接:
- Microsoft Atlas:下载它并搜索 AtlasCompat.js。
- 行为
- My AJAX Engine:请参阅 controls/jcl.js。