
本文介绍一种通过代理和手动同步机制,使“合并对象”对属性的修改能反向更新原始对象的方法,解决 javascript 中对象展开运算符仅支持浅拷贝、无法自动同步的问题。
本文介绍一种通过代理和手动同步机制,使“合并对象”对属性的修改能反向更新原始对象的方法,解决 javascript 中对象展开运算符仅支持浅拷贝、无法自动同步的问题。
在 JavaScript 中,使用展开运算符({...objA, ...objB})创建的合并对象是完全独立的副本——所有属性值均按基本类型值或引用地址复制,但后续对 bigObject 的赋值操作不会影响 objectA 或 objectB。这是因为属性本身(如 "key1" 对应的数字 1)是原始值,而对象的“属性绑定”并非语言原生支持的引用关系。要实现“修改合并对象即修改源对象”的效果,必须建立显式的双向同步逻辑。
核心思路:属性变更 → 主动回写到源对象
答案提供的方案采用显式同步函数 + 源对象元数据标记的方式:
- 将原始对象数组存入 bigObject.sourceObjects;
- 修改 bigObject 属性后,调用 rebuildMergedObject() 遍历所有源对象,将当前 bigObject 中同名属性的值主动赋值回去。
const objectA = { key1: 1, key2: 2, key3: 3 };
const objectB = { key4: 4, key5: 5, key6: 6 };
// 创建合并对象,并附加源对象引用
const bigObject = { ...objectA, ...objectB };
bigObject.sourceObjects = [objectA, objectB];
// 修改合并对象属性
bigObject.key1 = 50;
// 手动触发同步:将 bigObject 的当前属性值写回所有匹配的源对象
function syncBackToSources() {
for (const prop in bigObject) {
if (prop === 'sourceObjects' || !bigObject.hasOwnProperty(prop)) continue;
for (const source of bigObject.sourceObjects) {
if (source.hasOwnProperty(prop)) {
source[prop] = bigObject[prop];
}
}
}
}
syncBackToSources();
console.log(objectA.key1); // 50 ✅
console.log(bigObject.key1); // 50⚠️ 注意事项:
- 仅适用于自有属性(own properties):hasOwnProperty() 确保不覆盖原型链属性;
- 无实时响应能力:需手动调用同步函数,适合批量操作后一次性提交场景;
- 键冲突时以最后遍历的源对象为准:若多个源对象含相同键,bigObject 中该键最终值会写入所有匹配源对象(非覆盖优先级);
- 不支持嵌套属性自动同步:此方案仅处理一层属性,深层结构需额外递归逻辑或改用 Proxy 实现拦截。
进阶建议:使用 Proxy 实现自动拦截(可选)
若需真正“透明”的引用式访问,可封装为 Proxy 对象,在 set 拦截器中自动定位并更新对应源对象:
function createLinkedMerge(...sources) {
const handler = {
set(target, prop, value) {
// 查找首个拥有该属性的源对象并赋值
for (const src of sources) {
if (src.hasOwnProperty(prop)) {
src[prop] = value;
return true;
}
}
// 若源中无此属性,则设在合并对象上(可选行为)
target[prop] = value;
return true;
},
get(target, prop) {
// 优先从源对象读取(保持最新值)
for (const src of sources) {
if (src.hasOwnProperty(prop)) return src[prop];
}
return target[prop];
}
};
return new Proxy({ ...sources[0], ...sources[1] }, handler);
}
const bigObject = createLinkedMerge(objectA, objectB);
bigObject.key1 = 99; // 自动同步至 objectA
console.log(objectA.key1); // 99该 Proxy 方案更贴近“引用语义”,但需注意性能开销与调试复杂度。生产环境推荐根据实际需求权衡:简单场景用显式同步,高频交互场景可考虑 Proxy 封装。

















