实现只读且防配置的核心API代理需用Object.defineProperties精确设置writable和configurable为false、enumerable为true,确保属性不可改值、不可删、不可重定义;仅Object.freeze()不够。

要实现一个“只读且防配置”的核心 API 代理,关键不是简单冻结对象,而是用 Object.defineProperties 精确控制每个属性的描述符:把 writable 设为 false、configurable 设为 false,同时确保 enumerable 符合预期(通常为 true 以便正常遍历和解构)。
明确目标:只读 + 防配置 = 不可改值、不可删、不可重定义
“只读”指不能修改属性值;“防配置”指不能删除该属性,也不能用 Object.defineProperty 再次修改其描述符(包括改成可写或可配置)。这两者必须同时满足,仅 Object.freeze() 不够——它对已有属性生效,但不阻止后续通过 defineProperty 覆盖(如果对象本身仍可配置),且无法精细控制新增属性行为。
-
writable: false → 赋值操作静默失败(非严格模式)或抛
TypeError(严格模式) - configurable: false → 无法 delete、无法重新 define、无法切换 getter/setter 与数据属性
-
enumerable: true(推荐)→ 保证
for...in、Object.keys()、解构等正常工作
用 defineProperties 批量定义受控属性
假设你有一组核心 API 方法(如 fetch、localStorage 封装),想代理并锁定它们:
const coreAPI = {
fetch: window.fetch.bind(window),
localStorage: window.localStorage,
JSON: JSON
};
const lockedAPI = {};
Object.defineProperties(lockedAPI, {
fetch: {
value: coreAPI.fetch,
writable: false,
configurable: false,
enumerable: true
},
localStorage: {
value: coreAPI.localStorage,
writable: false,
configurable: false,
enumerable: true
},
JSON: {
value: coreAPI.JSON,
writable: false,
configurable: false,
enumerable: true
}
});
此时 lockedAPI.fetch = null 无效,delete lockedAPI.fetch 返回 false,再次 Object.defineProperty(lockedAPI, 'fetch', {...}) 会直接抛错。
结合 Proxy 实现动态拦截 + 静态锁定双保险(进阶)
若需对未声明的属性也拒绝访问(比如防止误用 lockedAPI.nonexistent),可在 defineProperties 基础上叠加 Proxy:
const proxyAPI = new Proxy(lockedAPI, {
get(target, prop) {
if (prop in target) return target[prop];
throw new ReferenceError(`API "${prop}" is not defined`);
},
set() {
throw new TypeError('API object is read-only');
},
deleteProperty() {
throw new TypeError('API object is non-configurable');
}
});
注意:Proxy 的拦截是运行时的,defineProperties 是静态元属性控制。二者互补——前者兜底未知访问,后者从底层封死已定义属性的篡改可能。
避免常见陷阱
-
不要省略
configurable: false:否则即使writable: false,仍可通过defineProperty改成可写 -
不要对函数对象额外 freeze:函数本身是对象,但只要其属性(如
.name、.length)不暴露为可配置属性,就无需冻结函数体;若需冻结函数内部状态,那是另一层设计 -
慎用
Object.freeze()替代:它递归冻结自有属性,但对原型链、getter/setter、新增属性无约束,且无法单独控制某几个属性的可枚举性

















