先追這段程式
本地 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}));
{"same":true,"title":"Revised"}| 核對項目 | 結果 | 意思 |
|---|---|---|
| event.detail===payload | true | 同一物件 |
| payload.title after listener | Revised | 監聽器已改原件 |
結果為何如此
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"}