修复 JavaScript 跨浏览器兼容性问题
在所有主流网络技术中,没有哪一项技术像 JavaScript 一样因其跨浏览器兼容性问题而饱受诟病。但即便纯 HTML 和 CSS 取得了长足进步,没有 JavaScript,你仍然很难轻松构建 Web 应用或网站。
在上周的文章中,我们详细探讨了HTML和CSS中遇到的跨浏览器兼容性问题。目前为止,我们已经了解了浏览器兼容性的基础知识,以及如何确保您的网站/Web应用程序具有跨浏览器兼容性。
本文延续上周的文章,探讨Web开发人员在使用JavaScript时常见的跨浏览器兼容性问题,并介绍相应的解决方法。
但在我们开始讨论真正的主题之前,有必要先了解一下 JavaScript 的基础知识和发展历程。
到目前为止,我们已经了解了跨浏览器兼容性的基础知识,以及如何确保您的网站/Web应用程序具有跨浏览器兼容性。我们也探讨了一些修复CSS和HTML跨浏览器兼容性问题的机制。
本文将探讨 JavaScript 的跨浏览器兼容性问题以及相应的解决方法。在正式开始讨论之前,我们首先需要了解 JavaScript 的基础知识和发展历程。
深入研究 JavaScript
过去十年间,Web 开发经历了飞速发展,各种设备——台式机、手机、平板电脑等——层出不穷。用于上网的浏览器数量也随之激增。这给设计师和开发者带来了新的挑战,因为不同的浏览器对 CSS 和 HTML 代码的解析方式各不相同。其原因在于,每个浏览器都有其独特的渲染引擎,负责以不同的方式渲染网页元素。CSS、HTML 和 JavaScript 构成了渐进增强的三层架构。渐进增强是一种创建跨浏览器兼容网页设计的技术,其开发过程中的首要任务是保持网页核心内容的完整性,而其他复杂的插件和功能则退居其次。20 世纪 90 年代 JavaScript 刚问世时,由于各浏览器开发公司都有自己独特的脚本实现方式(这主要是为了争夺市场主导地位),因此出现了严重的跨浏览器兼容性问题。虽然现在这类问题已不复存在,但处理 JavaScript 的跨浏览器兼容性问题仍然会让开发者头疼不已。
JavaScript 代码问题主要出现在开发者在网页中添加不支持旧版浏览器的功能、使用错误的文档类型声明 (DOCTYPE) 或浏览器嗅探代码实现不完整/不正确的情况下。除非实现处理 JavaScript(或其他脚本语言)的标准机制,否则 JavaScript 的跨浏览器兼容性问题将持续存在。让我们来探讨一下这些 JavaScript 的跨浏览器兼容性问题,并了解一些修复机制。
你知道吗?信用卡号生成器是一款可以方便地生成随机IP地址的工具。它能生成包含所有必要信息的有效信用卡号,例如姓名、地址、有效期、CVV码和安全码(PIN)。
常见的 JavaScript 问题
在深入探讨 JavaScript 的跨浏览器兼容性问题之前,我们首先需要了解一些常见的 JavaScript 问题。本文假设您已熟悉 JavaScript 并具备一定的 JavaScript 开发经验。
- 内存泄漏是开发者经常遇到的问题之一。内存泄漏指的是应用程序之前使用的内存不再被使用。然而,由于某些原因(例如全局变量处理不当、DOM 引用超出范围等),已分配的内存没有被释放回“空闲”内存池。内存泄漏的常见原因包括全局变量处理不当和 DOM 引用超出范围。“Chrome 分析工具”可用于内存分析并识别内存泄漏。以下是 Chrome 内存分析工具运行的示例截图。
-
JavaScript 会按照代码在文档中出现的顺序执行。因此,务必在代码加载完毕后再引用它。如果在代码加载完成之前就引用它,则会导致错误。
-
与其他语言不同,在 JavaScript 中,如果向函数传递“参数数量不正确”,不会抛出错误。如果这些参数是可选的,代码将正常执行。但如果函数中必须使用这些参数,或者不使用它们,则可能会出现问题,甚至改变函数的功能。建议采用统一的命名约定,以便于识别此类问题。
-
相等运算符是 JavaScript 的基础,但必须精确使用。赋值/相等运算符 (==) 和严格相等运算符 (===) 之间存在区别。它们主要用于条件语句,误用 (==) 而不是 (===) 会导致功能问题。为了找出这些看似愚蠢却代价高昂的错误,需要进行彻底的代码审查。
-
变量的使用应根据其作用域(局部变量和全局变量)进行区分。请确保对不同类型的变量使用一致的命名规范,以便于代码维护。同时,
请确保您的源代码没有任何语法错误。 -
在 JavaScript 中添加 DOM 元素被认为是一项开销较大的操作。它之所以被广泛使用,主要是因为 JavaScript 使得 DOM 的实现变得简单。在某些情况下,你可能需要连续添加 DOM 元素,但这并非最佳实践。在这种情况下,你可以使用文档片段(document fragments),因为它具有更高的效率和性能。
-
JavaScript 数组的起始索引是 0 而不是 1。如果您要创建一个包含 10 个元素的数组,则应该将索引设置为 9(数组元素 0 到 9),而不是 10(数组元素 0 到 10)。引用超出数组边界的元素会导致错误。
-
在同步操作中执行耗时任务可能会降低网页/Web应用程序的性能。请务必将该逻辑移至异步操作,以免占用过多CPU资源。由于该操作本质上是异步的,因此在使用操作中涉及的变量时必须格外小心,因为它们可能无法反映最新值(因为异步操作可能仍在执行中)。建议开发人员使用Promise对象,该对象返回异步操作完成的状态(成功/失败)。以下是一个使用Promise的示例代码。
- 在循环内部错误使用函数,导致功能失效。
常见的跨浏览器 JavaScript 问题
到目前为止,我们已经探讨了一些基本的 JavaScript 问题;接下来,让我们看看解决这些问题的一些机制:
您知道吗?CRC32B 哈希生成器可以让您根据给定的字符串快速生成 CRC32B 校验和哈希值。此外,您还可以通过网页浏览器生成 CRC32B 哈希值。
库的使用
与我们之前讨论过的 jQuery 库类似,许多库(包括原生库和第三方库)可能不被某些浏览器版本所支持。在使用库之前,建议您对其进行全面分析(包括浏览器支持、功能支持等)。您还应该查看库的“开发历史”,因为不应该出现库更新很少,甚至在您使用后就再也没有更新的情况!
使用用户代理和浏览器嗅探
每个浏览器都有一个用户代理字符串,用于识别用户访问您的网站/Web应用程序时所使用的浏览器。开发人员会使用浏览器嗅探代码,根据用户使用的浏览器来调整用户界面/用户体验/功能。以下列出了一些常见的用户代理字符串。
开发者可以使用 `navigator.userAgent.indexOf('user-agent')`,其中 `user-agent` 是用户代理字符串(如上表所示)。以下代码示例展示了开发者如何根据浏览器类型实现相应的功能。
现代 JavaScript 特性检测
在处理错误和无法识别的特性方面,JavaScript 不像 HTML 和 CSS 那样灵活。当遇到语法错误、缺少大括号、分号或其他问题时,JavaScript 一定会发出错误信号。
ECMAScript 6 (ES6)/ECMAScript Next 标准中实现了许多新特性,但许多旧版浏览器并不支持这些特性。例如,我们之前讨论过的“Promise 对象”在旧版浏览器中无法正常工作。“类型化数组”是另一个例子。“箭头函数”是 ES6 中引入的一个非常有用的特性,它为 JavaScript 函数的编写提供了一种简洁的方式。箭头函数不绑定到自身的 `this` 对象,也就是说,箭头函数内部的上下文是静态定义的。现代 JavaScript 开发者大量使用这一特性,但它在旧版浏览器(例如 IE、Firefox、Chrome 等)中也不受支持。Safari 浏览器就不支持箭头函数。
那么,如何确保 JavaScript 功能在旧版浏览器上也能流畅运行呢?解决方法是验证所使用的功能是否受旧版浏览器支持。您可以使用 caniuse 等在线资源进行验证;只需输入功能名称,它就会显示支持该功能的浏览器版本。例如,以下是“箭头函数”的示例。红色条目表示该功能不受支持。
根据目标受众,您应该支持所有最新浏览器以及部分旧版本浏览器(具体取决于您的初步市场调研)。您可以查看这些网络分析工具,它们将帮助您更好地了解客户。您还可以选择“条件执行”,以便在用户使用旧版浏览器时始终有“回退机制”。许多旧版浏览器不支持 WebRTC(视频会议)、地图 API 等。在下面的示例中,我们使用了地理位置 API;为此,我们使用了 Navigator 对象的 geolocation 属性。如果浏览器不支持地图 API,则会为用户提供使用静态地图的选项(作为回退选项)。
开发者需要导入许多 JavaScript 库才能轻松使用其功能。使用库的好处在于,开发者无需从头开始编写所有代码,因为库已经支持这些功能。
JavaScript 转译
如果您想为旧版浏览器提供支持,但又不想使用浏览器嗅探、功能检测等技术,那么“转译”是一个便捷的选择。简单来说,转译可以将使用最新 ES6/ECMAScript 特性的 JavaScript 代码转换为可在旧版浏览器上运行的 JavaScript 代码。
您可以使用像 Babel 这样流行的 JavaScript 转译工具,只需在“左侧”输入最新的 JavaScript 代码,它就会在“右侧”输出转译后的代码。
您知道吗?Lorem lpsum 生成器是一种可以方便地生成随机 IP 地址的工具。它是一种常用于图形和网页设计的占位符文本。
聚酯纤维填充物
与增强功能并缩短开发时间的第三方库类似,Polyfill 也包含可在项目中使用的第三方 JavaScript 文件。然而,Polyfill 与库的不同之处在于,Polyfill 能够提供原本不存在的功能。例如,您只需使用对应功能的 Polyfill,即可支持 WebRTC/Promise/其他基于 ES6 的特性。
您可以查看此列表,其中详细介绍了 JavaScript 特性对应的 Polyfill。我们来看一个例子。下面的代码片段展示了如何使用 Polyfill 来支持 ES6 中引入的 startsWith 特性。
解决常见的 JavaScript 问题
JavaScript 调试器
断点通常用于调试,当命中断点时,代码执行会暂停,开发者可以查看各种细节,例如调用堆栈、监视变量、内存信息等。JavaScript 有一个名为 `Debugger` 的关键字,当遇到该关键字时,JavaScript 代码的执行也会暂停。这与在代码中插入断点类似。
var x = 6 * 5;
debugger;
/* Logic here */
或者,您也可以使用传统的调试方法,即在 Chrome 浏览器中使用“JavaScript 控制台”来调试代码。您可以通过“工具”->“JavaScript 控制台”选项打开 JavaScript 控制台。
浏览器开发者工具
浏览器开发者工具可用于清除 JavaScript 代码中的警告和错误。它对于调试代码也很有用,因为开发者可以在代码的特定位置插入断点。
如果您使用的是 Chrome 或 Firefox 浏览器,只需在“加载代码”窗口后右键单击,然后单击“检查元素”。浏览器开发者工具还有一个“调试器”选项卡,开发者可以在其中插入断点、查看调用堆栈、向监视窗口添加变量等等。
以下是 Firefox 浏览器开发者工具的截图。
开发者还可以使用 Console API 在开发阶段打印日志。建议针对不同用途使用不同类型的控制台日志。例如,`console.log()` 可用于调试,`console.assert()` 用于断言,`console.error()` 用于错误处理。
代码编辑器插件
许多编辑器都内置或提供可下载的代码检查插件,用于修正 JavaScript 代码中的警告和错误。Atom 是一款流行的开源 IDE,它拥有代码检查插件。开发者可以安装 lint、jslint 和 linter-jshint 等插件来检查源代码。这些插件会在开发窗口底部的单独面板中显示代码中存在的警告和错误。下图是 Atom IDE 显示源代码警告的截图。
衬垫
代码检查工具(Linter)用于确保代码质量更高、对齐正确且无错误。就像 HTML 和 CSS 代码检查工具一样,JavaScript 代码检查工具对于维护代码质量也至关重要,无论 JavaScript 代码的大小如何。代码检查工具可以自定义不同级别的错误/警告报告。一些常用的 JavaScript 代码检查工具包括 JSHint 和 ESLint。
解决常见的 JavaScript 问题
除了我们目前讨论的 JavaScript 问题之外,开发者还需要解决许多通用问题。一些常见的通用问题包括:
-
变量名、函数名等使用了错误的大小写/拼写。许多经验丰富的开发人员都会不小心使用大小写/拼写错误的内置函数。例如,您可能会使用 `getElementByClassName()` 而不是 `getElementsByClassName()`。
-
在进行代码审查时,审查员应确保return 语句之后没有代码,因为这些代码是冗余的(或无法执行的)。
-
对象表示法与普通赋值不同,你需要检查对象的成员名称是否用逗号 (,) 分隔,以及成员名称是否与其值用冒号 (:) 分隔。
-
虽然这是一个非常基本的做法,但请检查分号(;)是否用在了正确的位置。
JavaScript 最佳实践
以下是一些 JavaScript 最佳实践:
-
始终将声明放在最前面。
-
遵循正确的变量、函数等命名规则。
-
在代码中始终使用“注释”。
-
使用 var 关键字声明局部变量。
-
务必初始化变量。
-
不要声明字符串、数字或布尔对象。
-
switch...case 语句中一定要有“default case”。
-
仔细查看 == 和 === 运算符的用法。确保它们用在了正确的位置。
-
将脚本放在页面底部。
用于解决跨浏览器兼容性问题的 JavaScript 框架
众所周知,无论应用程序或网站的大小或复杂程度如何,都会存在跨浏览器兼容性问题。正如我们从上述几点中看到的,使用 JavaScript 会加剧跨浏览器兼容性问题。但这并不意味着您可以完全避免使用 JavaScript!
有很多 JavaScript 框架可以帮助开发跨浏览器兼容的网站。其中一些最知名的框架包括:
-
React JS
-
AngularJS
-
离子
-
Ember JS
这些框架有助于解决 JavaScript 的跨浏览器兼容性问题。它们还能帮助开发者创建可在不同浏览器(例如 Google Chrome、Mozilla Firefox、Safari 等)上兼容的单页应用程序。
文章来源:https://dev.to/lambdatest/fixing-javascript-cross-browser-compatibility-issues-51pl









