更改对象的 [[Prototype]] 后,JavaScript 环境最终会恢复吗?

Will a JavaScript environment eventually recover after changing the [[Prototype]] of an object?

所以,我已经阅读了 MDN disclaimers and warnings, I've read a great answer on the subject, but there's still something I want to know. This question actually came from an answer I gave to another question, here

假设我决定做肮脏的事。我会后悔一辈子的事情。这会让我永远蒙羞,让我的家族名誉扫地。一个有目的的、深思熟虑的结局--

好了,够了。无论如何,这里是:

let proto = Object.getPrototypeOf(Function.prototype);

Object.setPrototypeOf(Function.prototype, {
  iBetterHaveAGoodReasonForDoingThis : "Bacon!"
});

//just to prove it actually worked
let f = (function(){});
console.log(f.iBetterHaveAGoodReasonForDoingThis);

// Quick, hide the evidence!!
Object.setPrototypeOf(Function.prototype, proto);

基本上,我在那里所做的是更改 Function.prototype 的原型,该对象几乎会影响您可以编写的每一段 JavaScript 代码。然后我改回来了。

我想说明原型链中的一个重大变化,它会影响大量代码并导致大量优化付诸东流。我不希望将其改回可以解决任何问题(如果有的话,我希望它会使性能变得更糟)。我很想知道它是否会,但如果它会,那不是我的意图。

我只想知道,经过这样的改变,JavaScript环境是否会开始恢复并重新开始优化?或者它会永远放弃并 运行 一切都处于去优化模式吗?是否有因此永远无法实现的优化?我可以相信,经过一段时间的恢复后,它最终会 return 恢复到正常状态吗?

就上下文而言,我说的是像最新版本的 V8 这样的引擎,而不是像 Internet Explorer 这样的东西使用的原始废话。我理解不同系统的答案可能不同,但我希望它们之间有一些共性。

这里是 V8 开发人员。这个问题没有简单的答案。

大多数 优化将"come back"(当然,代价是花费额外的CPU 时间)。例如,必须丢弃的优化代码最终将被重新编译。

某些 优化将永远禁用。例如,V8 在(只要)它知道原型链没有被破坏时会跳过某些检查。如果它看到一个应用程序修改了原型链,它就会从那时起安全地进行处理。

让事情变得更加复杂的是,细节会随着时间的推移而改变。 (这就是为什么在这里列出更具体的情况没有多大意义,抱歉。)

背景:

JavaScript 中有很多地方代码 可能 做某事,JavaScript 引擎必须检查,但大多数代码不会'不要这样做。 (举个例子,从数组的原型中继承缺失的元素:['a', ,'c'][1] 几乎总是 returns undefined 除了 如果有人做了 Array.prototype[1] = 'b'Object.prototype[1] = 'b'.) 因此,在为函数生成优化代码时,引擎必须在两个选项之间做出决定:

(A) 始终检查有问题的事物(在示例中:遍历数组的原型链并检查每个原型以查看它是否在该索引处具有元素)。假设执行这段代码需要 2 个时间单位。

(B) 乐观地假设数组原型没有元素,并跳过检查(示例中:甚至不看原型,只是 return undefined)。假设这将执行时间减少到 1 个时间单位(快两倍,耶!)。然而,为了正确,引擎现在必须密切关注所有数组的原型链,如果任何元素出现在任何地方,则必须找到并丢弃所有基于此假设的代码,代价为 1000时间单位。

考虑到这种权衡,引擎首先遵循快速但有风险的策略 (B) 是有道理的,但是当它失败一次时,它会切换到更安全的策略 (A),以便避免再次支付1000次单位罚款的风险。

您可以争论 "even just once" 是否是最佳阈值,或者网站是否应该在放弃 (B) 之前获得 2、3 甚至更多的免费通行证,但这不会改变根本权衡。