event对象不可浅拷贝,因其为只读原生实例,无自有可枚举属性,关键属性为getter-only;应显式提取所需字段并object.freeze()封装,或在闭包中直接使用const解构。

Event 对象本身是只读的,不能直接用浅拷贝“复制出可写副本”——它不是普通对象,而是浏览器原生事件实例,其属性(如 target、currentTarget、type、preventDefault 等)由规范定义为只读或不可枚举,且多数属性在构造后即冻结。
为什么 Event 对象不适用常规浅拷贝
Object.assign()、扩展运算符或 {...event} 都无法真正拷贝 Event 实例:
- Event 不是普通 plain object,没有可枚举的自有属性(
Object.keys(event)返回空数组); - 它的关键属性(如
target)是 getter-only,没有 setter,也无法通过 defineProperty 添加; - 尝试
{...event}得到的是空对象{};Object.assign({}, event)同样返回空对象; - 即使手动提取部分字段(如
{ type: e.type, target: e.target, timeStamp: e.timeStamp }),得到的只是普通对象,已脱离 Event 原型链,不再具备stopPropagation()、preventDefault()等方法。
实际可行的只读属性提取方案
若目标是“安全地保留某些 Event 属性用于后续只读访问”,应显式选取、封装,而非拷贝整个 Event:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 只提取你需要的字段,构造一个新对象,并用
Object.freeze()冻结顶层:
const safeSnapshot = Object.freeze({
type: e.type,
targetId: e.target?.id,
timeStamp: e.timeStamp,
isTrusted: e.isTrusted
});
- 这样得到的对象所有自有属性均为只读、不可配置、不可枚举,符合只读语义;
- 注意:
e.target是 DOM 元素,本身不可深冻结(会报错),所以只取其id、className等基本属性; - 避免直接赋值
target: e.target,否则新对象仍持有对可变 DOM 节点的引用,违背“只读数据”的初衷。
需要保留事件行为时的正确做法
如果逻辑依赖 e.preventDefault() 或 e.stopPropagation(),就不要试图拷贝 Event——而是把处理逻辑封装在事件回调内,或通过闭包捕获必要上下文:
- 在事件处理器中立即读取所需字段,存入局部常量;
- 用
const { type, isTrusted } = e;解构并标记为const,从语言层防止重赋值; - 如需异步使用,可包装成轻量不可变结构:
Promise.resolve().then(() => console.log(type)),而非传递 event 对象本身。
补充:不要用 JSON 方式序列化 Event
JSON.stringify(e) 会返回 {} 或抛错,因为 Event 没有可序列化的自有可枚举属性,且内部含有函数(preventDefault)和循环引用(target 指向自身树)。这不是限制问题,而是设计使然——Event 就不该被序列化或拷贝。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










