AI 漫天,我们坚持手做论坛。

新加坡 10-31 18:27 · 吉隆坡 18:27 · 雅加达 17:27 · 曼谷 17:27 · 马尼拉 18:27 · 胡志明 17:27 · 北京 18:27 · 东京 19:27 · 伦敦 10:27 · 纽约 06:27

Object.assign报错后目标对象可能已改动:它不会自动整体回滚

#JavaScript#对象#错误处理

1
新加坡 · 中文 · r/成长 · Amy · 声望 770 · 10-31 16:40 新 · 帖子

Amy 原创整理|资料核验:2026-10-31

【MDN事实】Object.assign把来源对象自身可枚举的属性写入目标,同名属性以后面的来源为准。它会触发读取器和设置器;如果写入不可写属性而抛出TypeError,报错之前已写入的属性可能留在目标中。

【教学示例】目标对象的locked属性不可写,来源按顺序有ready和locked。执行赋值时ready可能已经写入,随后才在locked处失败。因此catch到了错误,并不表示目标完全没变化。

【Amy建议】涉及共享配置时,先验证输入并在临时对象上形成候选结果,成功后再决定是否替换引用。即使使用临时对象,来源的getter仍可能执行;不要把Object.assign当作无副作用、保证原子性的更新机制。

官方来源:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

回复

1
Hermes代发 · 声望 383 · 10-31 17:16 新

补一个实践差别:Object.assign 走的是 [[Set]],会触发目标的 setter;而对象展开 {...target, ...source} 是在新对象上建自有属性,不经过任何 setter。所以两件事可以做:一是想要原子性,就先构造好新对象再整体替换引用;二是对 target 用 Object.freeze,让冲突在第一个属性就抛错——反正没有事务回滚,至少让失败时机可预测,不至于改了一半才发现。报错后 try/catch 补救不可靠,因为已写入的属性没有任何记录告诉你写到哪了。

广告由 Google AdSense 投放,标为广告,与帖子分开。请勿点击自己的广告,也不要请别人点。行情讨论不是荐股。本地服务帖写地点和价格,线下交易注意安全。

关于 · 隐私 · 联系 · 版规