如何创建JavaScript对象';什么是永久的?
我可以强制不改变对象的原型吗 注意有一些要求:如何创建JavaScript对象';什么是永久的?,javascript,prototype,prototype-programming,prototype-chain,Javascript,Prototype,Prototype Programming,Prototype Chain,我可以强制不改变对象的原型吗 注意有一些要求: 对象的行为应该与常规对象文字(添加/删除/配置/修改对象上的属性和描述符)一样 从字面上看,只有新的限制是原型是永久的 因此,除了原型是永久性的之外,我不想添加任何其他限制(像Object.seal/freeze/preventExtensions这样的工具对对象施加更多限制) 我是否必须使用monkey patch一个选项是(注意,这会从扩展中锁定整个对象,而不仅仅是从被修改的原型中锁定): “严格使用”; 常量obj={}; 对象扩展(o
- 对象的行为应该与常规对象文字(添加/删除/配置/修改对象上的属性和描述符)一样
- 从字面上看,只有新的限制是原型是永久的
Object.seal/freeze/preventExtensions
这样的工具对对象施加更多限制)
我是否必须使用monkey patch一个选项是(注意,这会从扩展中锁定整个对象,而不仅仅是从被修改的原型中锁定):
“严格使用”;
常量obj={};
对象扩展(obj);
setPrototypeOf(obj,{possibleNewPrototype:'foo'})代码>我想出了一个猴子补丁来做我想做的事情,在下面的代码片段中公开了一个lockPrototype
函数
我所知道的唯一问题是,如果其他一些代码在我的代码之前运行,那么它们可以从对象.prototype.\uuuu proto.\uuuu
描述符中获得对对象.setPrototypeOf
和setter的原始引用,从而解决我的猴子补丁。但在大多数情况下,我认为这是可行的。本机实现不会有这个问题
在我接受自己的答案之前,还有其他问题吗
下面是一个示例(标记为lockPrototype.js
的部分是实现,标记为test.js
的部分是如何使用它):
//lockPrototype.js/////////////////////////////////////////////////////
const oldSetPrototypeOf=Object.setPrototypeOf
const lockedObjects=新的弱集
Object.setPrototypeOf=函数(obj,proto){
if(锁定对象具有(对象))
抛出新的TypeError(“#的原型已锁定。”)
调用(对象、对象、原型)
}
常量(prototype)描述符=Object.getOwnPropertyDescriptor(Object.prototype,'.\uuu protou')
Object.defineProperty(Object.prototype,'.'原型'.'{
…原始描述符,
集合(原型){
if(lockedObjects.has(this))
抛出新的TypeError(“#的原型已锁定。”)
__proto___描述符.set.call(this,proto)
},
})
//出口
功能锁定原型(obj){
//此行为类似于Object.seal/freeze/preventExtensions
if(对象类型!=“对象”和对象类型!=“功能”)
返回obj
锁定对象添加(obj)
}
//test.js//////////////////////////////////////////////////////////////
//从“/lockPrototype”导入{lockPrototype}
常数a={}
常数b={}
常数c={}
常量proto={n:5}
锁定原型(b)
锁原型(c)
setPrototypeOf(a,proto)//工作正常
console.log('a.n',a.n)//5
设置超时(()=>{
console.log('b.n:',b.n)//未定义
设置超时(()=>{
console.log('c.n',c.n)//未定义
})
c、 \uuuu proto\uuuuu=proto//抛出
})
Object.setPrototypeOf(b,proto)//throws
您是否真的错过了Object.seal
,或者由于某种原因它不适合您?而且,Object.freeze
更适合你。@WiktorZychla啊哈!我没有尝试过,但我的直觉认为这不管用,因为我认为作为一个getter/setter,setter仍然可以接受这个值并按照它喜欢的方式去做(就像在用户代码setter中一样)!谢谢这是否意味着用户代码设置者应该检查对象是否被密封,并在这种情况下抛出?否则,为什么Object.seal会禁用\uuuuuu proto\uuuuuu
,而不是常规用户设置程序?@WiktorZychla提出了一个新问题:\uuuuuu proto\uuuuu
已被弃用。不要再使用它。@trusktr指定它只是为了在web兼容环境之间保持一致性。我没有将此标记为答案,因为我需要对象的行为就像普通对象文字一样(添加/删除属性),唯一的限制是原型是永久的。有了这个限制,你在寻找什么-当且仅当对象仍然可扩展时(如果不可扩展,也不能添加其他属性),可以使用SetPrototypeOf
internal方法来更改对象的底层原型。有没有什么我可能遗漏的问题?在使用TypeScript一段时间后,我开始喜欢防止扩展的想法,因为它加强了类型安全。如果我的用户真的想将新数据与对象关联,他们可以使用映射或WeakMap。我相信这将有助于减少代码的脆弱性。防止扩展的想法在我身上逐渐形成。