函数不可序列化,因其本质是行为而非数据;json、structuredclone等仅复制状态,无法表达闭包、内部属性及动态绑定等运行时信息,刻意忽略函数是安全设计。

因为函数在 JavaScript 中是不可序列化的值,不是数据,而是可执行逻辑单元。
函数本质不是“数据”,无法被通用序列化协议表达
JSON、structuredClone 等机制的设计目标是复制「状态」(state),而非「行为」(behavior)。函数包含作用域链、闭包变量、执行上下文等运行时私有信息,这些无法用纯数据结构描述。比如:
- 闭包捕获的变量:函数内部引用了外层函数的局部变量,这些变量不在函数自身属性中,无法通过遍历键名获取;
-
不可枚举的内部属性:如
[[Environment]]、[[Code]]等,JS 引擎不暴露给用户代码; -
动态绑定特性:
this、arguments、new.target都依赖调用时环境,拷贝后无法复现原语义。
刻意忽略是安全选择,而非技术遗漏
如果强行“拷贝”函数,结果往往是危险的假象:
- JSON.stringify 直接删掉函数属性——避免静默产生不可用空对象;
- structuredClone 抛出
DataCloneError——明确拒绝非法操作; - 手写递归深拷贝通常跳过函数类型(
typeof fn === 'function')——防止把闭包逻辑错误地“平铺”成无意义空壳。
真正需要函数复用时,应换思路
不靠拷贝,而靠设计:
- 把逻辑抽离为纯函数(无闭包、无 this 依赖),放在共享模块中 import 使用;
- 用工厂函数生成新实例:
const createHandler = () => () => console.log('new');; - 若必须保留绑定上下文,用
bind()或箭头函数显式固化,再作为数据属性传入对象。
所以不是“拷贝失败”,而是“不该拷贝”——函数属于行为契约,不是可复制的数据快照。










