簡體   English   中英

如何使JavaScript對象的原型永久化?

[英]How to make a JavaScript object's prototype permanent?

我可以強制不改變對象的原型嗎?

注意! 有一些要求:

  • 該對象應該像常規對象文字一樣(在對象上添加/刪除/配置/修改屬性和描述符),
  • 從字面上看, 唯一的新限制是原型是永久性的。

所以除了原型是永久性的,我不想添加任何其他限制(像Object.seal/freeze/preventExtensions這樣的工具對對象施加更多限制)。

我是否需要猴子補丁🐒Object.prototype Object.prototype.__proto__Object.setPrototypeOf才能實現這一目標?

一個選項是Object .prevent Extensions() (注意,這會從擴展中鎖定整個對象,不會僅鎖定原型的修改):

 'use strict'; const obj = {}; Object.preventExtensions(obj); Object.setPrototypeOf(obj, { possibleNewPrototype: 'foo' }); 

 'use strict'; const obj = {}; Object.preventExtensions(obj); obj.__proto__ = { possibleNewPrototype: 'foo' }; 

我想出了一個猴子補丁來做我想做的lockPrototype ,在下面的代碼片段中展示了一個lockPrototype函數。

我所知道的唯一問題是,如果其他代碼在我的代碼之前運行,那么他們可以從Object.prototype.__proto__描述符獲得對Object.setPrototypeOf和setter的原始引用,從而解決我的猴子補丁問題。 但對於大多數情況,我認為它會起作用。 本機實現不會出現此問題。

在我接受自己的答案之前,還有其他問題嗎?

這是示例(標記為lockPrototype.js的部分是實現,標記為test.js的部分是如何使用的):

 // lockPrototype.js ///////////////////////////////////////////////////// const oldSetPrototypeOf = Object.setPrototypeOf const lockedObjects = new WeakSet Object.setPrototypeOf = function(obj, proto) { if (lockedObjects.has(obj)) throw new TypeError("#<Object>'s prototype is locked.") oldSetPrototypeOf.call(Object, obj, proto) } const __proto__descriptor = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__') Object.defineProperty(Object.prototype, '__proto__', { ...__proto__descriptor, set(proto) { if (lockedObjects.has(this)) throw new TypeError("#<Object>'s prototype is locked.") __proto__descriptor.set.call(this, proto) }, }) // export function lockPrototype(obj) { // this behavior is similar to Object.seal/freeze/preventExtensions if (typeof obj !== "object" && typeof obj !== "function") return obj lockedObjects.add(obj) } // test.js ////////////////////////////////////////////////////////////// // import {lockPrototype} from './lockPrototype' const a = {} const b = {} const c = {} const proto = { n: 5 } lockPrototype(b) lockPrototype(c) Object.setPrototypeOf(a, proto) // works fine console.log('a.n', an) // 5 setTimeout(() => { console.log('bn:', bn) // undefined setTimeout(() => { console.log('c.n', cn) // undefined }) c.__proto__ = proto // throws }) Object.setPrototypeOf(b, proto) // throws 

(小提琴: https//jsfiddle.net/trusktr/Lnrfoj0u

您應該在Chrome devtools控制台中看到的輸出是:

在此輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM