一个实用的克隆接口应自动识别数组或对象、支持浅/深拷贝模式、妥善处理特殊值与循环引用、保持原始构造器;推荐分基础层、增强层、策略层实现,示例函数兼顾兼容性与安全性。

数组克隆与深拷贝接口的集成,关键在于按需选择合适方案,并封装成可复用、易维护、边界鲁棒的工具函数。不能简单堆砌方法,而要结合数据结构特征、运行环境、特殊值容忍度来设计统一入口。
明确克隆接口的设计目标
一个实用的克隆接口应满足:
- 自动识别输入是否为数组或普通对象,统一处理逻辑
- 支持浅拷贝与深拷贝两种模式,通过参数显式控制
- 对函数、undefined、Symbol、Date、RegExp、BigInt 等特殊值有明确定义(如跳过、序列化、抛错或保留原引用)
- 能检测并安全处理循环引用,避免栈溢出
- 保持原始构造器(如 Uint8Array、Map、Set 等需单独适配)
推荐分层实现结构
不建议用单一 JSON 方法兜底,也不宜全靠递归硬写。更合理的做法是分层组合:
- 基础层:提供纯浅拷贝(如展开符、slice、Array.from)和基础深拷贝(带循环引用检测的递归函数)
- 增强层:扩展对 Map/Set/Date/RegExp/TypedArray 的支持,用 instanceof + 构造器重建
-
策略层:暴露配置项,例如
clone(arr, { deep: true, ignore: ['function', 'undefined'] })
轻量但健壮的接口示例
以下是一个兼顾兼容性与安全性的最小可行实现(ES6+,无外部依赖):
function clone(value, options = {}) {
const { deep = false, handleCircular = true } = options;
// 原始值直接返回
if (value === null || typeof value !== 'object') return value;
// 处理日期、正则、错误等内置类型
if (value instanceof Date) return new Date(value);
if (value instanceof RegExp) return new RegExp(value);
if (value instanceof Error) return Object.assign(new value.constructor(), value);
// 数组与普通对象统一处理
const isArr = Array.isArray(value);
const result = isArr ? [] : {};
// 浅拷贝逻辑
if (!deep) {
return isArr ? [...value] : { ...value };
}
// 深拷贝:带循环引用缓存
const seen = new WeakMap();
function _deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (seen.has(obj)) return seen.get(obj);
const cloned = Array.isArray(obj) ? [] : {};
seen.set(obj, cloned);
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
cloned[key] = _deepClone(obj[key]);
}
}
return cloned;
}
return _deepClone(value);
}
调用方式简洁:clone([1, {a: 2}]) 或 clone(data, { deep: true }),语义清晰,易于测试和扩展。
与现代框架或工具链集成要点
在实际工程中,该接口常需对接上下文:
- React/Vue 中建议默认启用深拷贝,避免响应式系统误判引用变更
- 配合 Immer 时,克隆可降级为浅拷贝,由 Immer 负责不可变更新
- Node.js 环境可引入
structuredClone(v17.0+)作为 fallback,它原生支持 Map/Set/Date/RegExp 等 - TypeScript 项目中应补全泛型定义,确保返回值类型与输入一致











