65.9K
CodeProject 正在变化。 阅读更多。
Home

跨浏览器 JavaScript

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (22投票s)

2005年12月15日

5分钟阅读

viewsIcon

166313

downloadIcon

1117

一个不为人知的技巧,可以通过实现一个小的兼容层来简化多浏览器编程。

引言

如果您需要实现一个大量使用 JavaScript 进行客户端效果或类似 AJAX 功能的 Web 应用程序,并且需要支持 Microsoft Internet Explorer 6.0 以上版本,那么您可能会在这里找到一个不为人知的技巧,通过实现一个小的兼容层来简化您的编程。

Microsoft Internet Explorer 和 Mozilla/FireFox 这两个浏览器都拥有根据 HTML、CSS 和 JavaScript 标准定义的许多功能,其中一些功能对于在客户端实现某些功能非常有用。由于这些不同平台提供了一些可扩展性功能,因此可以扩展一个浏览器,使其拥有开箱即用时不存在于另一个浏览器中的方法和属性。

JavaScript 原型

浏览器平台中包含的 JavaScript 语言解释器提供几乎相同的功能。实际上没有必要使用此功能来为其中一个平台提供一些缺失的功能,但它仍然是一个有趣的功能,并且可以为您提供扩展两个平台的可能性。

JavaScript 的对象类型,最好称之为 JavaScript 的内置对象(StringNumberArray 等),它们是 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 对象(如 spandivp 等)的 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

在实现启用 AJAX 的框架时,JavaScript 编码变得越来越重要。目前使用这种方法的 JavaScript 库不多,但一些较新的库会这样做。这里有一些链接:

© . All rights reserved.