JavaScript 可通过 Proxy 的 set 和 get 陷阱实现属性读写时的类型断言与自动转换:set 中按 schema 校验并转换值,get 中兜底返回默认值或二次校验,最终封装为 createTypedObject 工厂函数。

JavaScript 中可以通过 Proxy 拦截对象属性的读写操作,在 set 和 get 陷阱中嵌入类型检查与自动转换逻辑,实现轻量、透明的“类型断言 + 强制转换”效果。核心思路是:写入时校验并转为目标类型,读取时确保返回值符合预期(如防止 undefined 或做兜底转换)。
定义类型规则与转换映射
先明确每个属性期望的类型(如 number、string、boolean),并为常见类型提供安全转换函数:
-
toNumber(x):用Number(x)转换,NaN时可返回默认值(如0)或抛错 -
toString(x):用String(x),空值转空字符串 -
toBoolean(x):按语义转换(如"true"、"1"、1→true)
规则可用对象描述,例如:
const schema = {
age: { type: 'number', default: 0 },
name: { type: 'string', default: '' },
active: { type: 'boolean', default: false }
};
用 Proxy 拦截 set 实现写入时断言与转换
在 set 陷阱中根据字段名查 schema,对新值做类型校验和转换,并只允许合法值写入内部存储(如一个私有目标对象):
- 若值为
undefined或null,直接用默认值 - 调用对应转换函数,失败时可静默处理或
throw错误 - 转换后存入目标对象,避免原始值污染
示例片段:
const target = {};
const handler = {
set(obj, key, value) {
const rule = schema[key];
if (!rule) return false; // 拒绝未声明字段
<pre class="brush:php;toolbar:false;">let converted;
switch (rule.type) {
case 'number':
converted = Number(value);
if (isNaN(converted)) converted = rule.default;
break;
case 'string':
converted = String(value);
break;
case 'boolean':
converted = ['true', '1', 1, true].includes(value) ? true : false;
break;
default:
converted = value;
}
obj[key] = converted;
return true;} };
用 Proxy 拦截 get 实现读取时兜底与类型保障
get 陷阱用于确保读取结果始终符合类型契约,尤其应对未赋值字段或中间被删改的情况:
- 若属性不存在或为
undefined,返回 schema 中定义的default - 可额外做一次类型校验(如发现
age是字符串但应为 number,则现场转换) - 避免暴露原始非法值,保持 API 表面“强类型”感
示例:
get(obj, key) {
const rule = schema[key];
if (!rule) return undefined;
<p>const raw = obj[key];
if (raw === undefined) return rule.default;</p><p>// 可选:运行时二次校验(如 number 字段意外存了 string)
if (rule.type === 'number' && typeof raw !== 'number') {
const num = Number(raw);
return isNaN(num) ? rule.default : num;
}
return raw;
}</p>
封装成可复用的工厂函数
把上述逻辑封装为函数,方便为不同 schema 创建带类型约束的对象:
function createTypedObject(schema) {
const target = {};
return new Proxy(target, {
set(obj, key, value) { /* 同上 */ },
get(obj, key) { /* 同上 */ }
});
}
<p>// 使用
const user = createTypedObject({
age: { type: 'number', default: 0 },
name: { type: 'string', default: '' }
});</p><p>user.age = '25'; // 自动转为 25(number)
user.name = null; // 自动转为 ''
console.log(user.age); // 25(number),不是 '25'
</p>
不复杂但容易忽略细节:需注意 in 操作符、Object.keys() 等不会触发 get,如需完全控制枚举行为,要配合 ownKeys 和 has 陷阱补充。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











