object.freeze对html编辑器配置无效,因其仅冻结顶层属性,无法阻止嵌套对象(如toolbarbuttons[0].icon)或深层配置(如plugins[0].config.maxfilesize)被修改,必须使用递归的deepfreeze并确保初始化前完成冻结。

Object.freeze(config) 为什么对 HTML 编辑器配置无效
因为 HTML 编辑器的常量配置(比如 toolbarButtons、formats、plugins)几乎全是嵌套结构:数组里含对象,对象里又有函数或子配置。而 Object.freeze 只冻结顶层属性,config.toolbarButtons[0].icon = 'x' 或 config.formats.p 的 attributes 字段仍可被随意改写——这在富文本场景下极易引发渲染错乱或功能失效。
必须用 deepFreeze 递归冻结所有嵌套层级
HTML 编辑器配置常见模式是:plugins: [{ name: 'image', config: { maxFileSize: 2097152 } }]。这种结构下,只冻 config 根对象毫无意义。你需要一个能穿透数组、对象、甚至深层嵌套的 deepFreeze:
- 跳过
null、undefined、原始值(string/number/boolean)和内置类实例(Date、RegExp、Map),它们不该出现在纯配置中 - 对每个
object或array类型值,先递归冻结其子项,再调用Object.freeze锁定自身 - 用
Object.getOwnPropertyNames遍历所有自有属性名(不含 Symbol),避免遗漏手动添加的字段 - 加
Object.isFrozen(obj)检查,防止重复冻结或循环引用崩溃
示例实现:
function deepFreeze(obj) {
if (obj == null || typeof obj !== 'object') return obj;
if (Object.isFrozen(obj)) return obj;
// 先冻结子项
Object.getOwnPropertyNames(obj).forEach(prop => {
if (obj[prop] !== null && typeof obj[prop] === 'object') {
deepFreeze(obj[prop]);
}
});
return Object.freeze(obj);
}
冻结时机错误等于没冻:必须在编辑器初始化前完成
很多项目把配置导出写成 export default Object.freeze({ ... }),但打包器(如 Vite/Webpack)可能提前解析或缓存未冻结版本;更危险的是,若某插件模块先 import config from './editor-config' 再传给 new Editor(config),那它拿到的仍是原始可变引用。
- Node.js 环境:在入口文件(如
main.js)最顶部同步加载配置,立即deepFreeze(config),再require('./editor') - 浏览器 ESM:用
import config from './editor-config.js'; deepFreeze(config);,且确保该语句位于模块顶层作用域,不包裹在函数或异步回调中 - 禁止在
getConfig()函数里返回冻结对象——调用方可能缓存了未冻结的旧引用
仅 freeze 不够,还要锁住全局绑定和原型链
即使配置对象被深冻结,攻击者仍可能通过以下方式绕过:
-
CONFIG = {}—— 如果CONFIG是挂载在window或globalThis上的变量,Object.freeze对它完全无效 -
CONFIG.__proto__.evil = 1—— 若冻结前没切断原型链,原型污染仍可生效
补全防护:
// 先深冻结对象
const EDITOR_CONFIG = deepFreeze({
toolbarButtons: ['bold', 'italic'],
formats: { p: { tag: 'p' } }
});
// 再锁住全局绑定
Object.defineProperty(globalThis, 'EDITOR_CONFIG', {
value: EDITOR_CONFIG,
writable: false,
configurable: false,
enumerable: true
});
// 切断原型链(防污染)
Object.setPrototypeOf(EDITOR_CONFIG, null);
真正难处理的不是冻结本身,而是配置对象一旦被任意模块提前引用,就再也无法“追加冻结”。所以核心不是“怎么冻”,而是“谁第一个拿到它”——这个控制权必须收回到你手里。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











