Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何创建JavaScript对象';什么是永久的?_Javascript_Prototype_Prototype Programming_Prototype Chain - Fatal编程技术网

如何创建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。我相信这将有助于减少代码的脆弱性。防止扩展的想法在我身上逐渐形成。