【问题标题】:How to replace javascript standard built-in objects?如何替换 javascript 标准内置对象?
【发布时间】:2020-10-29 09:06:40
【问题描述】:

我的客户基于 Chromium 构建自己的应用程序,他们的 navigator.appVersion 是 AppleWebkit/534+

但令我惊讶的是,他们用自己的替换了 javascript 标准内置对象,例如,查看下面的地图,

他们的 Map 有类似的方法,

arr:Array[0]
isEmpty:function
remove:function

但是没有像 has, keys, values 这样的标准 Map 方法,在这里查看 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map(顺便说一句,我们在这里需要 Map 而不是普通的 js 对象的原因是我们需要密钥不是字符串)

我很好奇,他们是怎么做到的?为什么会有人这样做!!

更重要的是如何恢复构建版本?

【问题讨论】:

  • 只需覆盖Map 构造函数。这没有什么不寻常的,即使它是不明智的。
  • 如果这是一个旧项目(至少可以追溯到 5 年以上),他们可能会用自己的抢占 ECMAScript 的标准 Map 对象。并不是他们故意覆盖它,而是他们不能等待浏览器原生支持它 - 基本上是 polyfill/ponyfill,除了他们使用不同的对象接口。
  • 我认为现在更重要的问题是如何恢复内置版本。
  • “我如何恢复内置版本” - 我认为你不能。一旦构造函数(即使是像 Map 这样的引擎提供的构造函数)被覆盖,您将无法取回它 - 至少在不创建单独的新 global(又名 window)上下文的情况下无法取回 - 但据我所知不能保证能够在不同的 JS 上下文之间传递构造函数(假设构造函数不可序列化)
  • 但是到目前为止我得到的答案呢?以及除了 Map = function() { ... } 有多少种方法可以覆盖 Map 构造函数

标签: javascript chromium v8


【解决方案1】:

我遇到了同样的问题,全局函数被覆盖了。

我的诀窍是使用iframecontentWindow 来获取原始函数:

这是代码,由于 iframe 政策,它在 StackOverflow 的 code-sn-ps 中不起作用,但它应该适用于您的环境:

// contaminated Map
Map = function() {
    this.foo = 'bar';
}
const map1 = new Map();
console.log(map1);

​
// restoring Map
const iframe = document.createElement('iframe');
document.body.append(iframe);
const OriginalMap = iframe.contentWindow.Map;
iframe.remove();
​
const map2 = new OriginalMap();
map2.set('foo', 'bar');
console.log(map2);

这是显示它有效的屏幕截图:

这更像是一种解决方法,不确定是否有更好的方法。

【讨论】:

  • 谢谢,我会尝试并回复您!
【解决方案2】:

他们是怎么做到的?

很简单:

Map = function() { ... }

为什么有人要这么做!!

正如其他 cmets 猜测的那样,可能是因为代码比内置 Map 的可用性更早。如果同样的代码也应该在旧版浏览器上运行,那么这个考虑可能仍然是相关的。

如何恢复构建版本?

另一个答案中的建议是一个有趣的想法......我想不出更好的方法。

也就是说:我猜您的任务是对现有代码库进行扩展/修改。在同一个代码库中有两个不同的Maps 听起来很令人困惑——对于在您之后处理此代码的任何人(可能是您自己,几个月后),很难理解发生了什么。所以我提出另一个建议:不要只在本地获取内置的Map,而是选择以下之一:

  • 使整个系统现代化以使用内置的 JavaScript Maps。替换手工地图的所有用途,然后删除该定义。在任何地方使用内置的Map。 (与您的客户确认他们是否同意您花时间在这方面。)
  • 坚持现有的,并在您的新代码中使用手工制作的地图。虽然它的功能有不同的名称,但似乎所有重要的功能都在那里。您可能会找到一个如何迭代此类地图的示例。 (这仍然会将上述替代方案留作未来的选择。)

【讨论】:

  • 我问了他们的 navigator.appVersion,是 AppleWebkit 534+ 我猜确实很老了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 2018-05-12
  • 1970-01-01
  • 1970-01-01
  • 2013-08-09
  • 2019-10-14
  • 1970-01-01
相关资源
最近更新 更多