object.assign 不会主动中断或抛错,但源对象的 getter 执行异常时会立即中止并抛出错误;它跳过 null/undefined 源,对原始值转包装对象处理,仅遍历可枚举自有属性。

Object.assign 本身不会在拷贝过程中“中断”或抛出错误——它是一个健壮的、容错性很强的浅拷贝方法。如果你观察到“错误后中断”,实际原因通常不是 Object.assign 自身报错,而是后续代码(比如访问拷贝结果中的 undefined 属性、调用不存在的方法、或源对象含有 getter 抛异常)导致的运行时错误。
理解 Object.assign 的行为特点
它会按顺序遍历每个源对象的**可枚举自有属性**,逐个赋值到目标对象上:
- 遇到 null 或 undefined 源对象,会跳过(不报错);
- 遇到原始值(如字符串、数字),会先转为对应包装对象,再提取其可枚举属性(例如 "abc" → ["0":"a","1":"b","2":"c"]);
- 如果某个源对象的某个属性是 getter,且该 getter 执行时抛出异常,则 Object.assign 会立即中止并把错误向上抛出 —— 这是最接近“拷贝中断”的真实场景。
捕获 getter 异常导致的中断
当源对象含危险 getter(如访问未初始化的 this.db.query)时,需提前防护:
const source = {
get risky() {
if (!this.db) throw new Error('DB not ready');
return this.db.fetch();
}
};
try {
Object.assign({}, source); // ⚠️ 此处会直接 throw
} catch (err) {
console.error('拷贝被 getter 中断:', err.message);
// 可降级:用 Object.getOwnPropertyDescriptors + try/catch 包裹 getter 访问
}
更安全的替代方案(按需选用)
若需强容错,避免任何中断,可手动实现可控拷贝:
-
过滤掉 accessor 属性:用
Object.getOwnPropertyNames()+Object.getOwnPropertyDescriptor()判断是否为 value 属性; - 对每个属性单独 try/catch:遍历 key,逐个赋值并忽略失败项;
- 用 structuredClone(现代环境):深度克隆且自动跳过不可序列化值(但不支持函数、undefined、循环引用);
- 使用第三方库如 lodash.cloneDeep:内置 getter 容错与错误隔离机制。
调试建议:快速定位中断源头
在疑似问题对象上运行以下检查:
Object.entries(Object.getOwnPropertyDescriptors(obj)).forEach(([key, desc]) => {
if (desc.get || desc.set) {
console.log(`⚠️ 含 accessor: ${key}`);
}
});
重点关注带 get 的属性,并确认其内部逻辑是否可能抛错。










