当前位置: 首页 > Web前端 > HTML5

JavaScript社区某库引发的“smooshdoor”事件是怎么回事?

时间:2023-04-05 18:28:51 HTML5

原文:MathiasBynenssmoosh的#SmooshGate常见问题解答?!发生了什么?!一项名为JavaScript特性Array.prototype.flatten的提议被证明与网络不兼容。FirefoxNightly中该功能的发布导致至少一个热门网站崩溃。鉴于相关代码是广泛使用的MooTools库的一部分,很可能还有更多网站受到影响。(虽然MooTools在2018年的新站点上并不常用,但它曾经非常流行,并且在许多已经运行的站点上仍然存在。)提案作者开玩笑地建议将flatten重命名为smoosh以避免兼容性问题。然而,并非所有人都知道这是一个玩笑,一些人开始误以为新名字已经敲定,事情迅速升级。什么是Array.prototype.flatten?Array.prototype.flatten按照指定的深度递归地展平数组,depth默认值为1。//展平一层:constarray=[1,[2,[3]]];array.flatten();//→[1,2,[3]]//递归展平,直到数组不再包含嵌套数组:array.flatten(Infinity);//→[1,2,3]同样的提议也包括数组。原型.flatMap。和Array.prototype.map一样,可以在参数中传入一个回调函数。[2,3,4].flatMap((x)=>[x,x*2]);//→[2,4,3,6,4,8]MooTools有什么问题?MooTools定义自己的非标准版本Array.prototype.flatten:Array.prototype.flatten=/*非标准实现*/;MooTools的扁平化实施不同于提议的标准。不过,这不是问题!当浏览器提供原生Array.prototype.flatten时,MooTools会覆盖原生实现。这可确保依赖于MooTools的代码按预期运行,无论本机扁平化是否可用。到目前为止,一切都很好!不幸的是,发生了其他事情。MooTools将所有自定义数组方法复制到Elements.prototype(Elements是MooTools特定的API):for(varkeyinArray.prototype){Elements.prototype[key]=Array.prototype[key];}for-inTraversing"可枚举”属性,它不包括像Array.prototype.sort这样的本地方法,但包括自定义属性Array.prototype.foo=whatever。但是-这是踢球者-如果你覆盖一个不可枚举的属性,例如Array.prototype.sort=whatever,那么该属性仍然是不可枚举的。目前,Array.prototype.flatten=mooToolsFlattenImplementation创建了一个枚举flatten属性,因此稍后会将其复制到Elements。但是,如果我们发布原生版本的flatten,它将变得不可枚举,并且不会被复制到Elements。任何使用MooTools并依赖于Elements.prototype.flatten的代码现在都被破坏了。虽然使原生的Array.prototype.flatten可枚举可能会解决问题,但它可能会导致更多的兼容性问题。每个依赖于for-in遍历数组的网站(这是一种不好的做法,但它被广泛使用)突然得到了那个flatten属性的循环迭代。这里更大的潜在问题是修改内置对象。扩展本机原型现在通常被认为是一种不好的做法,因为它不能很好地与其他库和第三方代码结合。不要修改不属于你的对象!我们为什么不保留现有名称并破坏网络?1996年,在CSS普及之前,并且早在“HTML5”出现之前,SpaceJam网站就已经启动并运行了。如今,该网站已平稳运行22年。这怎么可能?多年来是否有人维护过该站点,每次浏览器供应商发布新功能时都会对其进行更新?事实证明,“不要破坏网络”是在HTML、CSS、JavaScript和网络上的任何标准中广泛使用的首要设计原则。如果新浏览器功能的发布导致现有网站停止工作,那对每个人都不利:受影响网站的访问者突然获得了糟糕的用户体验;网站所有者从一个功能完善的网站转到一个无法正常运行的网站,并且网站所有者没有进行任何更改;用户在看到“仅支持XXX浏览器”后会切换浏览器,因此推出新功能的浏览器厂商会失去市场份额。一旦知道兼容性问题,其他浏览器供应商就拒绝实施此功能。导致功能规范与实际实现不匹配(“只是虚构的作品”),这对标准化过程不利。当然,回想起来MooTools做错了一件事——但破坏网络并没有惩罚他们(MooTools),而是惩罚了用户。这些用户不知道MooTools是什么。或者,我们可以找到其他解决方案,用户可以继续使用网络。这是否意味着无法从Web平台中删除不良API?在极少数情况下,可以从网络中删除不良功能。即使只是弄清楚是否可以删除某个功能也是一项棘手的工作,需要大量遥测来量化有多少页面改变了它们的行为。但是,如果功能不够安全、对用户有害或很少使用,则可以这样做。和showModalDialog()都是已成功从Web平台中删除的不良API示例。为什么不修复MooTools?给MooTools打补丁是个好主意,这样它就不再扩展内置对象。但是,它并没有解决手头的问题。即使MooTools发布了补丁版本,所有使用它的现有网站也必须更新,这样兼容性问题才会消失。我可以只更新我网站中使用的MooTools副本吗?理想情况下,MooTools会发布一个补丁,每个使用MooTools的网站都会在第二天神奇地更新。问题解决了吧?!不幸的是,这是不现实的。即使有人以某种方式确定了整组受影响的网站,也可以设法找到每个网站的联系信息,成功联系所有网站所有者并说服他们所有人执行更新(这可能意味着完全重建他们的网站代码库),整个这个过程可能需要长达数年的时间。请记住,其中许多站点都已过时,可能无法维护。即使维护人员仍然存在,他们也很可能不是像您这样技能高超的Web开发人员。由于网络兼容性问题,我们不能指望每个人都改变他们已经运行了七八年的网站。TC39的工作流程是什么样的?JavaScript语言基于ECMAScript标准,TC39是负责JavaScript语言更新和发展的委员会。“Smooshgate”事件让一些人误以为“TC39想把flatten改名为smooth”,但这是一个没有很好传播的笑话。像重命名提案这样的重大决定不是草草做出的,不是由一个人做出的,也绝对不是在GitHub评论中做出的。TC39对功能提案有明确的分级流程。ECMAScript提案和任何重大更改(包括方法更新)在TC39会议期间进行讨论,并且在正式提交之前需要委员会的完全批准。在这种情况下,Array.prototype.flatten提案经历了几个阶段的讨论,一直到第3阶段,表明该功能已准备好在Web浏览器中实现。在实施过程中出现其他规范问题的情况并不少见。在这种情况下,最重要的反馈是在尝试发布之后出现的:该功能在当前状态下破坏了Web。即使在浏览器发布新功能后,TC39进程也不会因为这些不可预测的问题而结束。TC39以协商一致方式运作,这意味着委员会必须就任何新的更改达成一致。即使smoosh是一个严肃的提议,委员会成员似乎也可能会反对更常见的名称,例如compact或chain。TC39会议上从未讨论过将flatten重命名为smoosh(尽管这不是玩笑)。因此,目前TC39官方对这个问题的立场是未知的。在下次会议达成共识之前,没有一个人可以代表整个TC39。TC39会议通常由具有高度多样化背景的人参加:一些人具有多年设计编程语言的经验,其他人使用浏览器或JavaScript引擎,以及不断壮大的JavaScript开发人员社区。接下来发生了什么下一次TC39会议将于本周举行。议程上有一个项目讨论扁平化及其网络兼容性问题。希望会议结束后我们能更多地了解接下来会发生什么。