JS干货| 浏览器缺点、浏览器的缺点修复等五大开辟题目解决之道

恣意一段重要的代码都须要关注无数的开辟题目。然则,个中对可复用JavaScript代码应战最大的五项题目如图14.2所示。

《JS干货| 浏览器缺点、浏览器的缺点修复等五大开辟题目解决之道》

图14.2 对可复用JavaScript代码应战最大的五项题目

五大开辟题目以下。

  • 浏览器缺点。
  • 浏览器的缺点修复。
  • 外部代码。
  • 浏览器回归。
  • 浏览器缺失的功用。

我们须要衡量处置惩罚这些题目所消费的时候与获得的收益。这些是不得不回答的题目。你剖析潜伏受众、开辟资源、开辟排期等,这些都是决定性要素。

当试图开辟可复用的JavaScript代码,我们须要斟酌一切的要素,还须要斟酌如今最盛行的浏览器,由于这些浏览器是我们的目的受众最可以运用的浏览器。其他不那末盛行的浏览器,我们最少保证代码可以文雅降级。比方,假如一个浏览器不支撑某API,我们应当小心我们的代码不会抛出任何异常,如许剩下的代码依然可以顺遂实行。

在接下来的小节中,我们将解说这些题目,以便更好地明白我们面临的应战以及怎样应对。

1 浏览器的bug和差别

当我们开辟可复用性JavaScript代码时,须要斟酌处置惩罚的题目之一是处置惩罚我们一定须要兼容的多种浏览器bug以及API的差别。只管浏览器愈来愈规范化,然则代码照样必需得完整符合浏览器供应的特征。

完成这一目的的要领很直接:我们须要完整的测试东西,足以掩盖代码经常使用的和不经常使用的用例。充足测试以后,在晓得开辟的代码将在支撑的浏览器中事变后,我们会觉得平安。假定浏览器没有后续变化,不会突破向后兼容性,我有一个隐约的预感,代码以至会在未来版本的浏览器中事变。在14.3节中,我们会视察特定的战略来处置惩罚浏览器bug和差别。

庞杂的处所是,当前浏览器bug会在未来的浏览器版本中被修复。

2 浏览器的bug修复

浏览器永久存在特定的毛病是很愚昧的——大部份浏览器bug终究都邑修复,把愿望寄托在浏览器bug上是很风险的开辟战略。最好体式格局是运用14.3节中的手艺,运用不会过期的变通计划。

在编写一个可重用的JavaScript代码时,我们愿望它可以延续运转很长时候。编写任何方面的网站(CSS、HTML等),浏览器宣布新版本后,我们不愿望再回去修复代码。

假定浏览器bug引发罕见的网站题目:为处置惩罚浏览器bug运用特别妙技,未来浏览器宣布新版本修复了bug,就会涌现题目。

处置惩罚浏览器破绽的题目是两重的:

  • 当bug终究被修复,我们的代码轻易破坏。
  • 我们没法为了防止网站破坏而压服浏览器厂商不修复bug。

近来正好发作了第2种状况的风趣的事例,关于scrollTop的bug(https://dev.opera.com/article…)。

当处置惩罚HTML DOM时,可以运用scrollTop和scrollLeft属性,修正当前元素的转动位置。然则当我们对根元素运用这些属性时,依据类型,将会返回转动的位置,IE11与Firefox浏览器严厉遵照了这则类型。而Safari、Chrome和Opera并没有恪守。假如试图修正根元素的转动位置时,不会发作任何事变。为了完成雷同的效果,我们只能在body元素上运用scrollTop和scrollLeft属性。

当面临浏览器的不一致性时,Web开辟者们经常检测当前浏览器的名字(经由历程用户代办字符串,后续会细致引见),然后在IE11和Firefox上对HTML元素运用scrollTop和scrollLeft属性,而在Safari、Chrome和Opera上则对body元素运用scrollTop和scrollLeft属性。躲避这类题目将会形成灾难性效果。由于许多网页明白编码指定在Safari、Chrome或Opera上运用body元素,这些浏览器没法真正修复这个bug,由于一旦修复,许多网页都没法运转。

这引出了另一个关于bug的看法:在一定某一功用是不是是潜伏的毛病时,运用类型举行考证!

浏览器的bug不同于未指明的API。参考浏览器类型异常重要,由于类型供应了确实的规范,浏览器运用这些规范举行开辟和完美代码。相比之下,一个未指明的API的完成可以会在任何时候发作转变(特别是试图成为规范化的完成)。在未指明的API不一致的状况下,你应当对预期输出举行测试。小心这些API未来可以发作的变化。

别的,bug修复和API的变化是有区分的。bug修复是很轻易预感的——浏览器终究将修复bug,纵然要花很长的时候,API变化更难发明。规范API不太可以转变,只管不是完整不足为奇,变化更有可以涌现未指明的API中。

荣幸的是,大多数Web运用递次出题目的状况很少发作。万一涌现题目,有效地提早预知是无效的方法(除非我们一一测试相干的API——然则如许一个历程的开支是恐怖的)。这类API的变化应当做回归处置惩罚。

下一个须要体贴的题目是,没有人是一座孤岛,我们的代码也不是,让我们研讨代码的影响局限。

3 外部代码和标记

任何可重用代码必需与缭绕它的代码共存。我们愿望代码运转在本身编写的网站或是别人开辟的网站上,我们都须要确保代码可以与其他代码共存。

这是一把双刃剑:我们的代码不仅必需可以禁受住可以写得很遭的外部代码,还必需得战胜环境对代码的不利影响。

我们须要小心的水平很大水平上取决于所运用的代码对环境的关注。比方,假如我们仅为单个或有限个网站编写可重用的代码,在某种水平上可以控制,可以少一些忧郁,由于我们晓得代码的运转对外部代码的影响递次,而且一旦有题目,我们可以自行修复。

{注重 } 

这个题目的重要水平足以用一本书来论述。假如你想更深切地探讨,我们强烈引荐Ben Vinegar 和 Anton Kovalyov 编写的《第三方JavaScript》一书(Manning, 2013, https:// www.manning.com/books/third-party-javascript)。

假如开辟代码将普遍用于未知环境(不可控的)中,则我们须要两重确认代码的健壮性。接下来议论一些完成代码健壮性的战略。

代码封装

为了防止我们的代码影响页面上的其他代码,最好实践是运用封装。平常来讲,封装指代码(犹如)存放在容器里。从广义上来讲,是一种限定接见其他对象组件的言语机制。Aunt Mathilda或许会总结为“各人自扫门前雪,莫管别人瓦上霜”。

在页面上引入我们的代码时,尽量少地影响全局代码,将会使Aunt Mathilda异常高兴。事实上,尽量少地运用全局变量,以至最好仅限一个,是很轻易的。

第12章中的jQuery,它是最盛行的客户端JavaScript库,也是最好的类型。jQuery引入一个名为jQuery的全局变量(一个函数),别号为$,它以至许可其他网页为$设置别号防止争执。

jQuery中险些一切的操纵都经由历程jQuery函数完成。其他函数(东西函数)被定义为jQuery的属性(第3章引见怎样将函数定义为另一个函数的属性),运用jQuery作为定名空间。我们可以运用雷同的战略。假定我们须要定义一组函数,我们将其定义在定名空间ninja下。

与jQuery相似,我们可以定义名为ninja()的全局函数以操纵传入的变量。比方:

var ninja = function(){ /* implementation code goes here */ }

运用我们设定好的定名空间定义东西函数:

ninja.hitsuke = function(){ /* code to distract guards with fire here */ }

假如我们不须要ninja作为函数,仅作为一个定名空间即可,我们可以运用以下定义体式格局:

var ninja = {};

建立空对象,随后在该对象上定义属性或要领即可。为了保证代码的封装,须要防止其他操纵,如修正已存在的变量、函数原型以至DOM元素。修正我们本身代码以外的任何内容,都可以引发潜伏的争执和殽杂。别的,只管我们战战兢兢地严厉恪守最好实践封装代码,但我们依然没法保证代码的行动。

榜样代码

有一个老笑话Grace Hopper在Cretaceous时代为代替职员消灭蛀虫时说:“你最不恶心的代码就是你本身写的代码。”看起来很嗤笑,然则当我们的代码与不可控的代码同时运转时,为了平安起见,我们须要假定最糟的状况。

只管一些代码编写工致,但也有可以潜伏地做一些出人意料的事,比方修正函数属性、对象属性和DOM元素的要领。这些都可以设有圈套。

在这类状况下,我们的代码只能做一些无伤大雅的事,比方运用JavaScript数组,平常状况下JavaScript数组只能是JavaScript数组。然则,假如一些页面上修正了数组的行动,我们的代码将没法运转,固然不是我们本身的缘由。

遗憾的是,处置惩罚这类题目没有牢固的准绳规范,然则我们可以采纳一些步伐。我们将在后续小节中引见保护性要领。

应对ID滥用

大部份浏览器具有一些反特征(我们不能称之为bug,由于这些特征是故意而为之),这些特征会使得代码不可预期地落入圈套从而运转失利。这些特征使得原始元素与增加在元素上的id或name属性发生关联。然则当id或name属性与元素上已存在的部份属性发生争执时,就会发作一些意料以外的状况。

检察以下HTML代码片断,视察id属性的滥用:

<form id="form" action="/conceal">
 <input type="text" id="action"/>
 <input type="submit" id="submit"/>
</form>

如今,在浏览器中可以如许挪用:

var what = document.getElementById('form').action;

我们希冀返回合理的form的action属性。大部份状况下是可以返回的。然则当搜检值的时候你会发明,返回的倒是input#action元素。为何?让我们尝尝其他元素:

document.getElementById('form').submit();

这条语句本应引发form提交,然则却返回script毛病:

Uncaught TypeError: Property 'submit' of object #<HTMLFormElement> is not a function

发作了什么呢?

浏览器将<form>元素内一切input元素都作为表单form的属性。这一特征最先看起来很轻易,增加到form属性的名称是input元素的id或name属性。假如input元素的id或name属性正好运用了form元素的属性,比方action或submit,这些form元素的初始属性就被替换为新的属性值,平常被毛病地指向DOM。因而,在input#submit元素建立之前,form.action的援用应指向<form>的action属性。在input#action元素建立以后,form.action的援用指向input#action元素。form.submit属性也发作了雷同的状况。

这是为了兼容过去的浏览器的处置惩罚要领,老式浏览器不具备猎取DOM元素的要领。浏览器厂商增加这类特征是为了轻易猎取form元素。现如今我们可以轻松地猎取DOM元素,然则依然留下了副作用。无论怎样,浏览器这类特别的“特征”可以引发代码中大批虚无缥缈的题目,在调试时须要服膺于心。当我们碰到属性被不测地转变成非预期的内容时,罪魁祸首有多是DOM滥用。幸亏我们可以在本身的代码中防止这类题目,防止编写有可以与规范属性发作争执的过于简朴的id或name属性,并可以引荐其他开辟者运用相似的战略。开辟历程当中特别须要防止submit值,以避免形成使人懊丧和疑心的bug行动。

款式和剧本的加载递次

平常我们希冀CSS规则在代码实行时已可用。确保在款式代码中定义的CSS规则在JavaScript代码实行时已可用的最好体式格局之一是,将外部款式表单安排在外部剧本文件之前。假如不如许做,可以引发意料以外的效果,由于剧本可以试图接见未定义的款式信息。遗憾的是,这类题目没法经由历程JavaScript剧本举行改正,只能经由历程手动修正用户文件处置惩罚。

后续几节中会引见一些关于外部代码关于代码运转的影响的基本示例。当其他用户试图将我们的代码集成进他们的网站时,会暴露出一些题目,那末应当怎样诊断这些题目,怎样设想适宜的测试用例来处置惩罚这些题目呢?偶然,当我们试图将其别人的代码集成进本身的页面时,会发明相似的题目,愿望本节引见的发起有助于处置惩罚这些题目。蹩脚的是,关于处置惩罚代码集成题目,除了采纳一些智慧的体式格局来编写防御性代码,没有其他更好的体式格局。接下来继续关注下一个题目。

4 回归

回归是在编写可复用、可维护性JavaScript代码时,碰到的最难的题目之一。由于浏览器的bug或不向后兼容的API发作变化(平常是未细致申明的API)致使代码不可预期地中断了。

{注重 } 

这里我们运用术语回归的典范定义:过去运用的特征不再运转了。这平常是无意的,也有多是细致斟酌后的效果。

预期的变化

一些API发作的可预感性的变化,我们可以提早检测并处置惩罚,如代码清单14.1所示。比方,Microsoft在 IE 9引入对DOM 2 的事宜处置惩罚机制(运用addEventListener要领绑定事宜),而过去的IE版本运用IE内置的attachEvent要领。关于 IE 9之前的代码,运用简朴的特征检测可以处置惩罚这类变化。

清单14.1 预期行将发作的API变化

function bindEvent(element, type, handle) {
  if (element.addEventListener) {
   element.addEventListener(type, handle, false);  ⇽--- 运用规范API绑定
 }
  else if (element.attachEvent) {
   element.attachEvent("on" + type, handle);  ⇽--- 运用专有API
 }
}

在本例中,不会过期的代码提早预知Microsoft将在IE浏览器中引入DOM规范。运用特征检测来推断浏览器是不是支撑规范API,若支撑,则运用addEventListener要领。假如不支撑,则检测是不是支撑attachEvent要领。

大部份未来的API变化是不轻易展望到的,而且没法展望未来的bug。这是本书强调测试的最重要缘由之一。面临不可预期的变化对我们代码的影响,最好实践是在浏览器刊行的版本中模仿测试,以疾速发明题目。

运用优异的测试套件并亲昵关注行将刊行的浏览器版本是处置惩罚未来的退步题目的最好体式格局。不是在开辟周期中,而是在一样平常测试中举行。在新刊行的浏览器版本中运转的这些测试,应当剖析到开辟周期中举行。

从以下网站可以猎取行将刊行的浏览器信息。

用功很重要。由于我们没法完整展望浏览器未来可以发生的bug,可行的最好体式格局就是对未来可以发作的状况时候保持小心。

浏览器厂商为了防止回归题目的发作,做了许多事变。浏览器平常将JavaScript库的测试套件集成进浏览器测试套件中,确保未来的回归不会直接影响这些库。虽然没法掩盖一切的题目(一定没法完整掩盖),但这是一个很好的末尾,表明浏览器厂商在尽量地防止发作那样的状况。

在本节中,我们引见了开辟可复用性代码时面临的4种重要题目:浏览器bug、浏览器bug修复、外部代码、浏览器回归。

本文摘自:JavaScript忍者秘笈(第2版)

[美] John Resig(莱西格),Bear Bibeault(贝奥特),Josip Maras(马瑞斯) 著

《JS干货| 浏览器缺点、浏览器的缺点修复等五大开辟题目解决之道》

  • jQuery之父John Resig典范力作全新改版
  • JavaScript高手进阶秘笈
  • 周全订正以涵盖 ES6 和 ES7 的观点

《JavaScript 忍者秘笈(第2版)》运用现实的案例清楚地解释每个中心观点和手艺。本书向读者引见了怎样控制 JavaScript 中心的观点,诸如函数、闭包、对象、原型和 promise,同时还引见了 JavaScript API, 包括 DOM、事宜和计时器。你将学会测试、跨浏览器开辟,一切这些都是高等JavaScript开辟者应当控制的妙技。

本书包括以下内容:

  • 运用函数、对象和闭包编写更高效的代码;
  • 学会防止JavaScript运用圈套;
  • 运用正则表达式编写简约的文本处置惩罚代码;
  • 运用 promise 治理异步代码;
  • 周全订正以涵盖 ES6 和 ES7 的观点。

在本节中,我们引见了开辟可复用性代码时面临的4种重要题目:浏览器bug、浏览器bug修复、外部代码、浏览器回归。

    原文作者:敏子
    原文地址: https://segmentfault.com/a/1190000019120758
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞