跳至內容
Astera Technology

CustomEvent 的 detail,原來仍是同一個物件

CustomEvent 發出後,detail 是否已成獨立副本?

下載完整個案資料及參考答案 ↓

先追這段程式

本地 EventTarget 收到標題 Draft 的 payload。監聽器先核是否同一物件,再把 detail.title 改為 Revised;之後讀原 payload。

完整原始程式
const target=new EventTarget();const payload={title:'Draft'};let same;
target.addEventListener('sample',event=>{same=event.detail===payload;event.detail.title='Revised';});
target.dispatchEvent(new CustomEvent('sample',{detail:payload}));
console.log(JSON.stringify({same,title:payload.title}));
確實的 console 輸出
{"same":true,"title":"Revised"}
值與執行位置
核對項目結果意思
event.detail===payloadtrue同一物件
payload.title after listenerRevised監聽器已改原件

結果為何如此

CustomEvent 保存傳入的 detail 值,觸發時沒有自動複製。監聽器透過同一參照改動,原物件也變。建立事件前複製外層,可分開這些文字欄;內層物件仍要另訂複製規則。

比較另一種寫法

若誤以為 detail 是受保護的歷史副本,Draft 就保不住。以下修正對這些平面欄位先作副本,監聽器只改副本。

另開的有限例子
const target=new EventTarget();const payload={title:'Draft'};let same,eventTitle;
target.addEventListener('sample',event=>{same=event.detail===payload;event.detail.title='Revised';eventTitle=event.detail.title;});
target.dispatchEvent(new CustomEvent('sample',{detail:{...payload}}));
console.log(JSON.stringify({same,title:payload.title,eventTitle}));
另一寫法的輸出
{"same":false,"title":"Draft","eventTitle":"Revised"}

試清邊界

{...payload} 能否連 payload.style 內層也隔離?

查看參考答案

不能。外層淺複製仍共用 style;要另複製會改的支,或按實際值類型選擇合適快照方式。

重新建立的邊界例子
const target=new EventTarget();const payload={style:{ink:'green'}};let sameStyle;
target.addEventListener('sample',event=>{sameStyle=event.detail.style===payload.style;event.detail.style.ink='purple';});
target.dispatchEvent(new CustomEvent('sample',{detail:{...payload}}));
console.log(JSON.stringify({sameStyle,ink:payload.style.ink}));
邊界例子的輸出
{"sameStyle":true,"ink":"purple"}

原始例子檔案