修改对象的[[Prototype]]后,JavaScript环境最终能否恢复?
关于修改对象[[Prototype]]后恢复JS环境的问题
嘿,这个问题我之前踩过类似的坑,来给你唠清楚——能不能恢复得看你是改了单个对象的原型,还是动了内置构造函数的原型(比如Object.prototype这种全局级别的),分两种情况说:
1. 只修改了单个对象的[[Prototype]]
这种情况完全可逆,只要你提前存好原来的原型引用,或者能重新拿到它,分分钟就能恢复。举个例子:
// 先保存目标对象原来的原型 const originalProto = Object.getPrototypeOf(myObj); // 刻意修改原型 Object.setPrototypeOf(myObj, someCustomProto); // 想恢复的话,直接改回去就行 Object.setPrototypeOf(myObj, originalProto);
要是你是用__proto__(虽然不推荐用这个)改的,同理,再把__proto__赋值回原来的原型就行。甚至如果是普通对象,原来的原型就是Object.prototype,直接用这个值恢复也没问题。
2. 修改了内置原型(比如Object.prototype、Function.prototype)
这种情况要复杂点,但大部分场景还是能救的:
- 替换了整个内置原型对象:比如你干了
Object.prototype = {}这种事。要是你提前存了原来的Object.prototype引用,直接赋值回去就搞定:Object.prototype = originalObjProto。要是没存也别慌——找一个在修改前创建的对象,用Object.getPrototypeOf(oldExistingObj)就能拿到旧的原型,再把它赋值给Object.prototype就行。不过要注意,修改后新建的对象原型会指向新的,但旧对象还是挂着旧原型,恢复后新对象的原型会变回正常的。 - 修改了内置原型上的方法:比如把
Object.prototype.toString改成了自定义函数。这种情况恢复起来更简单,拿浏览器环境举例,你可以创建一个独立的iframe,从里面拿到干净的原生方法:
const iframe = document.createElement('iframe'); document.body.appendChild(iframe); // 从iframe的干净环境里拿原生toString const cleanToString = iframe.contentWindow.Object.prototype.toString; // 替换回被修改的方法 Object.prototype.toString = cleanToString; // 用完删掉iframe document.body.removeChild(iframe);
Node.js环境的话,可以用vm模块创建一个隔离上下文,从里面获取干净的内置方法。
极端情况:原型链彻底崩坏
要是你把Function.prototype这种核心原型改坏了,导致连Object.setPrototypeOf这类内置函数都没法正常工作,那基本就没辙了——只能重启JS环境:浏览器刷新页面,Node.js重启进程。毕竟核心原型被破坏后,整个JS的函数调用逻辑都可能崩掉,没法再执行恢复代码了。
最后多说一句:虽然修改[[Prototype]]能实现一些特殊需求,但JS引擎会对原型链做大量优化,修改原型会直接破坏这些优化,导致代码性能暴跌,日常开发里真的不推荐这么干~
内容的提问来源于stack exchange,提问作者GregRos
相关产品推荐
相关产品推荐

