自定义克隆策略的核心是按需控制属性保留、忽略、转换与特殊处理。通过白名单/黑名单筛选字段,对特定键值映射,手动处理不可序列化类型(Date、RegExp、函数、自定义类),控制嵌套深度与循环引用,并封装为可复用函数。

自定义克隆策略的核心,是绕过通用方案的“一刀切”限制,按需控制哪些属性保留、哪些忽略、哪些转换、哪些特殊处理。
明确需要干预的字段或类型
不是所有数据都需要原样复制。比如表单对象中可能含临时 UI 状态(isEditing、hoveredId),日志对象里有 timestamp 字段应重置,或者 API 响应里的 __meta 元信息不该进入新副本。
- 用白名单只克隆业务关键字段:
['id', 'name', 'items', 'createdAt'] - 用黑名单过滤非序列化字段:
['tempId', 'ref', 'onSubmit', '_cache'] - 对特定键做值映射:把
status: 'draft'自动转为'pending'
处理不可序列化的值
JSON.stringify() 会丢掉函数、Symbol、undefined、Date、RegExp 等;structuredClone() 虽支持多数类型,但不支持自定义类实例或私有字段。这时需手动接管:
- Date → 转成 ISO 字符串或时间戳再还原:
new Date(obj.date?.toISOString()) - RegExp → 提取 source 和 flags 重建:
new RegExp(obj.pattern.source, obj.pattern.flags) - 函数 → 根据用途决定:跳过(日志/事件回调)、替换成空函数、或注入调试桩
- 自定义类实例 → 检查 constructor,调用其静态
from()方法或手动提取可序列化属性
控制嵌套行为与循环引用
递归实现时,WeakMap 是检测循环引用的标准手段;但自定义策略还可进一步细化:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
- 指定最大递归深度,避免栈溢出(如仅深拷贝前 3 层)
- 对某些嵌套对象强制浅拷贝(如共享配置对象
config.theme不重复复制) - 遇到特定构造器(如
HTMLCanvasElement)直接跳过或返回 null - 对 Map/Set 等集合,选择是否保留其迭代顺序或只拷贝键值对数组
封装成可复用的克隆函数
把上述逻辑整合为带选项的函数,比每次手写更可靠:
function customClone(obj, options = {}) {
const { whitelist = null, blacklist = [], transform = {} } = options;
const seen = new WeakMap();
<p>function clone(value) {
if (value === null || typeof value !== 'object') return value;
if (seen.has(value)) return seen.get(value);</p><pre class="brush:php;toolbar:false;">let result;
if (value instanceof Date) {
result = new Date(value);
} else if (value instanceof RegExp) {
result = new RegExp(value.source, value.flags);
} else if (Array.isArray(value)) {
result = [];
} else {
result = {};
}
seen.set(value, result);
for (const key in value) {
if (!value.hasOwnProperty(key)) continue;
if (blacklist.includes(key)) continue;
if (whitelist && !whitelist.includes(key)) continue;
const newVal = transform[key] ? transform[key](value[key]) : clone(value[key]);
result[key] = newVal;
}
return result;}
return clone(obj); }
调用示例:customClone(data, { blacklist: ['tempRef'], transform: { createdAt: () => new Date() } })

















