先追這段程式
用展開語法複製草稿,再改副本的 title 和 style.ink。哪一項會牽動原件?
const original={title:'Draft',style:{ink:'green'}};
const copy={...original};copy.style.ink='purple';copy.title='Copy';
console.log(JSON.stringify({original,copy,sameStyle:original.style===copy.style}));
{"original":{"title":"Draft","style":{"ink":"purple"}},"copy":{"title":"Copy","style":{"ink":"purple"}},"sameStyle":true}| 欄位或參照 | 改動後原件 | 改動後副本 |
|---|---|---|
| title | Draft | Copy |
| style.ink | purple | purple |
| style identity | 與副本共用 | sameStyle: true |
結果為何如此
展開語法把自有、可列舉屬性的值放到新外層物件。title 是文字值,style 卻是物件參照,兩份資料仍指向同一 style。修改前要另複製這一支;以下修正並非萬用深層複製。
比較另一種寫法
有新外層物件,並不保證內層原值保留。以下重新用綠色原件,同時複製 style;沒有改的 meta 支仍然共用。
const original={title:'Draft',style:{ink:'green'},meta:{size:4}};
const copy={...original,style:{...original.style,ink:'purple'}};copy.title='Copy';
console.log(JSON.stringify({originalInk:original.style.ink,copyInk:copy.style.ink,sameStyle:original.style===copy.style,sameMeta:original.meta===copy.meta}));
{"originalInk":"green","copyInk":"purple","sameStyle":false,"sameMeta":true}試清邊界
只想改副本的 style.ink,複製應做到哪一層?
查看參考答案
外層 note 和 style 都要新建,再在該支設定 ink。其他內層若也要改,需逐支決定怎樣複製。
const original={style:{ink:'green'}};const copy={...original};copy.extra=1;
console.log(JSON.stringify({sourceHasExtra:Object.hasOwn(original,'extra'),copyHasExtra:Object.hasOwn(copy,'extra'),sameStyle:original.style===copy.style}));
{"sourceHasExtra":false,"copyHasExtra":true,"sameStyle":true}