为何无法冻结DOMStringList?Chrome中Object.freeze操作报错咨询
这个问题问到点子上了!其实核心原因和浏览器提供的**宿主对象(host objects)**特性密切相关,和JS原生对象的规则有很大区别:
宿主对象不受ES标准完全约束:
Object.freeze是ECMAScript标准定义的方法,但像DOMStringList这类DOM相关的对象属于浏览器提供的宿主对象。浏览器有权决定这类对象是否遵循ES的所有规则,为了自身内部机制的稳定,很多时候会禁止对这类对象执行冻结、扩展等操作。DOMStringList本身是只读且受浏览器管控的集合:
location.ancestorOrigins返回的列表是浏览器根据当前页面的嵌套上下文(比如iframe层级)自动维护的,它的内容和属性从设计上就是不可修改的。你可以用Object.getOwnPropertyDescriptors查看它的属性描述符:console.log(Object.getOwnPropertyDescriptors(location.ancestorOrigins));会发现大部分属性都是
writable: false、configurable: false的状态,而冻结操作本质是强化这种不可修改性,但浏览器已经对这类对象做了底层限制,甚至直接拦截了freeze操作。安全机制的限制:
ancestorOrigins涉及到跨域上下文的敏感信息,浏览器需要严格防止这类数据被篡改。如果允许冻结或者修改,可能会被恶意脚本利用来伪造祖先源信息,带来跨域安全风险。因此浏览器从根源上禁止了对这类对象的冻结操作。
简单来说,这类DOM宿主对象不是普通的JS对象,浏览器出于规范兼容性、内部机制维护和安全防护的多重考虑,限制了Object.freeze这类操作对它们生效,所以执行Object.freeze(location.ancestorOrigins)时会抛出Uncaught TypeError: Cannot freeze错误。
内容的提问来源于stack exchange,提问作者Max Koretskyi

