原文: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?在极少数情况下,可以从网络中删除不良功能。即使只是弄清楚是否可以删除某个功能也是一项棘手的工作,需要大量遥测来量化有多少页面改变了它们的行为。但是,如果功能不够安全、对用户有害或很少使用,则可以这样做。
