深拷贝默认不复制函数属性,因其含闭包、原型等不可序列化信息;JSON与递归拷贝均忽略或出错;推荐跳过函数、白名单保留引用或解耦逻辑,structuredClone亦不支持。

JavaScript 中深拷贝默认不复制函数属性,因为函数是引用类型且具有不可序列化特性,多数深拷贝方案会直接跳过或丢失它。
为什么函数在深拷贝中常被丢弃
函数不是纯数据:它包含执行逻辑、闭包环境、原型链等运行时信息,无法像字符串或数字那样“值化”。JSON 方法(JSON.parse(JSON.stringify(obj)))完全忽略函数;递归拷贝若未显式处理,也会把函数当作普通对象递归,最终可能出错或浅拷贝引用。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。
保留函数的几种可行方式
- 不拷贝,只保留引用:多数业务场景中,函数本就不该被“复制”,而是共享。深拷贝函数既无必要也不安全(比如闭包变量会被重复捕获),直接跳过函数字段是合理选择
-
手动白名单提取:在深拷贝逻辑中加判断,对特定 key(如
onSubmit、transform)单独保留原函数引用:if (key === 'callback') cloned[key] = obj[key]; -
用 Function 构造器重建(慎用):可通过
new Function('return ' + obj.fn.toString())()尝试重建,但会丢失闭包、无法处理箭头函数和严格模式,且存在安全风险,不推荐用于生产环境 - 标记+序列化策略:提前将函数转为可序列化的描述(如方法名+参数结构),深拷贝后再通过映射表还原调用,适用于配置类场景(如表单验证规则)
实际建议
除非有明确需求(例如沙箱环境隔离执行上下文),否则不要尝试“真正复制”函数。标准深拷贝函数(如 Lodash 的 cloneDeep)默认忽略函数;浏览器原生 structuredClone()(2022 年起支持)也明确不支持函数、Promise、Error 等非可转移对象。遇到必须携带行为的场景,更推荐解耦数据与逻辑——把函数抽离为独立模块或依赖注入,而非塞进待拷贝的数据对象里。

















