作者: Mathias Bynens
smoosh?! 发生了什么?!
一项名为 JavaScript 功能的 提案
Array.prototype.flatten
证明与 web 不兼容在 Firefox Nightly 中发布该功能会导致 至少一个受欢迎的网站 中断鉴于有问题的代码是广泛使用的 MooTools 库的一部分, 很可能会有更多网站受到影响(尽管 MooTools 在 2018 年并不常用于新网站, 但它曾经非常流行, 并且仍然存在于许多已经正在运行的网站上)
该提案笔者开玩笑地建议 把 flatten 重命名为 smoosh , 以避免兼容性问题
但是, 并非所有人都知道这是一个笑话, 有些人开始错误地认为这个新名字已经被确定, 并且事情迅速升级
Array.prototype.flatten
是什么?
Array.prototype.flatten
递归地将数组展按照指定的 depth 进行展平, depth 的默认值为 1
- // Flatten one level:
- const array = [1, [2, [3]]];
- array.flatten();
- // [1, 2, [3]]
- // Flatten recursively until the array contains no more nested arrays:
- array.flatten(Infinity);
- // [1, 2, 3]
同样的提议还包括
Array.prototype.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 = /* non-standard implementation */;
MooTools 的 flatten 实现与建议的标准不同但是, 这并不是问题! 当浏览器提供了原生的
Array.prototype.flatten
时, MooTools 会覆盖原生实现这可确保依赖 MooTools 的代码按预期运行, 无论原生 flatten 是否可用到现在为止还挺好!
不幸的是, 发生了其他事情 MooTools 将其所有自定义数组方法复制到 Elements.prototype ( Elements 是 MooTools 特定的 API):
- for (var key in Array.prototype) {
- Elements.prototype[key] = Array.prototype[key];
- }
for - in 遍历可枚举属性, 其中不包括像原生方法
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 之前, Space Jam 网站 就已经开始运行了今天, 该网站已经顺利运行 22 年了
来源: http://www.tuicool.com/articles/jAzue2i