javascript深拷贝过滤敏感字段应采用递归遍历跳过指定键名,而非json序列化;可手动实现、结合structuredclone预处理,或用lodash的clonedeep与omit组合,注意循环引用、不可枚举属性及精确字段匹配。

在 JavaScript 中做深拷贝时过滤敏感字段,核心思路是:不依赖简单序列化(如 JSON.parse(JSON.stringify())),而是用递归遍历对象/数组,在复制过程中跳过指定的敏感键名。
手动递归 + 白名单/黑名单控制
这是最灵活、可控性最强的方式。你可以定义一个需要排除的字段列表(如 ['password', 'token', 'secret', 'auth']),在遍历时检查当前键是否在其中,跳过该属性即可。
示例代码:
function deepCloneWithoutKeys(obj, excludeKeys = []) {
if (obj === null || typeof obj !== 'object') return obj;
if (Array.isArray(obj)) {
return obj.map(item => deepCloneWithoutKeys(item, excludeKeys));
}
const result = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
// 跳过敏感字段
if (excludeKeys.includes(key)) continue;
result[key] = deepCloneWithoutKeys(obj[key], excludeKeys);
}
}
return result;
}
// 使用
const user = {
name: 'Alice',
password: '123456',
token: 'abc123',
profile: { age: 30, email: 'a@example.com' }
};
const safeCopy = deepCloneWithoutKeys(user, ['password', 'token']);
// → { name: 'Alice', profile: { age: 30, email: 'a@example.com' } }
用 structuredClone 配合预处理(现代浏览器)
structuredClone 是原生深拷贝 API,但不支持过滤。可先对源对象做“脱敏处理”(即删除敏感字段的副本),再克隆。
注意:这个操作会修改临时对象,不污染原始数据。
- 创建源对象的浅层副本(用
{...obj}或Object.assign({}, obj)) - 递归删除敏感字段(可用上面的逻辑,或只删一层后交给
structuredClone) - 调用
structuredClone拷贝已清洗的对象
借助 Lodash 的 cloneDeep + omit 组合
如果你已在项目中使用 Lodash,可以组合 omit(支持路径语法)和 cloneDeep 实现简洁写法:
const _ = require('lodash');
const user = {
name: 'Bob',
credentials: { password: 'xxx', apiKey: 'yyy' },
settings: { theme: 'dark' }
};
// 过滤多层敏感字段(支持点号路径)
const safe = _.cloneDeep(
_.omit(user, ['password', 'credentials.password', 'credentials.apiKey'])
);
⚠️ 注意:_.omit 默认只处理第一层,要深层过滤需配合 _.unset 或自定义遍历。
避免踩坑的关键细节
- 不要用 JSON 方式过滤:它会丢掉函数、undefined、Symbol、Date、RegExp、循环引用,且无法在序列化中途干预字段
-
注意原型链和不可枚举属性:上面示例只处理自有可枚举属性;如需保留不可枚举属性,要用
Object.getOwnPropertyNames+Object.getOwnPropertyDescriptor - 循环引用要单独处理:基础递归版本遇到循环引用会爆栈,生产环境建议用 Map 缓存已访问对象
-
字段名匹配要谨慎:全等匹配(
===)最安全;避免模糊匹配导致误删(比如把passwordResetToken当成password删掉)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











