Object.seal仅锁定对象结构,不阻止已有可写属性值的修改;它禁止增删属性、删除属性及修改描述符,但允许如iteratorConfig.batchSize = 1等合法赋值,且对嵌套对象无效。

Object.seal 不是用来“完美防止篡改”的工具,它只做一件事:锁定对象的结构。对迭代器核心配置而言,seal 的价值在于守住“字段边界”——不让业务层误加新键、删关键键、或偷偷把 config.timeout 改成不可写,但它**不阻止你把 timeout 从 3000 改成 0**。是否“完美”,取决于你对“篡改”的定义。
明确 seal 能防什么、不能防什么
调用 Object.seal(iteratorConfig) 后:
- ✅ 新增属性失败:
iteratorConfig.maxDepth = 5静默无效(严格模式直接报错) - ✅ 删除属性失败:
delete iteratorConfig.strategy返回false - ✅ 修改属性描述符失败:
Object.defineProperty(iteratorConfig, 'batchSize', { writable: false })报错 - ❌ 修改值仍合法:
iteratorConfig.batchSize = 1成功(只要原属性writable: true) - ❌ 嵌套对象不受控:
iteratorConfig.api.retryOptions仍是普通对象,可任意增删改
为什么迭代器配置适合用 seal 而非 freeze
迭代器常需运行时微调,比如:
- 灰度阶段临时开启
debug: true - 根据网络状况动态降级
concurrency: 2 - i18n 切换时更新
labelFormatter函数
这些是合法变更,Object.freeze 会一刀切禁止,反而迫使开发者反复解冻/赋值,增加出错风险。seal 在保持结构稳定前提下,保留了必要的灵活性。
真正防“无意篡改”的三步加固法
仅靠 seal 不够。推荐组合策略:
- 构造后立即 seal:在配置对象完全初始化完毕、任何模块导入前执行,避免中间态被修改
-
对嵌套子对象手动 seal:如
iteratorConfig.api、iteratorConfig.cache等关键子对象,逐个调用Object.seal() -
导出只读访问器,不暴露原始引用:
const rawConfig = { batchSize: 10, strategy: 'breadth', api: { timeout: 8000 } }; Object.seal(rawConfig); Object.seal(rawConfig.api); export const getIteratorConfig = (key) => { if (!(key in rawConfig)) throw new Error(`Invalid config key: ${key}`); return rawConfig[key]; };
检查与兜底建议
上线前加一道校验:
- 用
Object.isSealed(iteratorConfig)确保密封生效 - 关键字段(如
strategy、batchSize)设为enumerable: false或用Symbol键,降低被遍历误改概率 - 非严格模式下错误静默,务必在入口文件顶部加
"use strict"










