Object.assign仅支持浅拷贝,需结合递归与策略映射表实现多层级主题配置合并:顶层用Object.assign,嵌套对象按路径策略(覆盖/深合并/数组拼接/保留)递归处理,最终封装为可动态扩展的ThemeEngine类。

Object.assign 本身只做浅拷贝,无法直接实现多层级合并(比如嵌套对象的属性级覆盖或保留),但可以结合递归、策略函数和配置元信息,构建一个灵活的主题配置引擎。核心思路是:用 Object.assign 处理顶层键合并,再对值为对象的字段按需递归合并,并允许每个层级指定策略(覆盖、深合并、数组合并、保留原值等)。
明确多层级合并的常见策略类型
主题配置中不同字段语义不同,不能一概而论:
-
覆盖策略(override):子主题完全替换父主题对应字段,如
colors.primary直接赋新值; -
深合并策略(deepMerge):对嵌套对象递归合并,如
typography下的h1、body分别更新; -
数组合并策略(concat/unique):如
fonts.families希望追加而非替换; -
保留策略(preserve):某些字段(如
id或version)应始终以基础配置为准,子主题不可覆盖。
设计可声明式配置的合并策略表
不硬编码逻辑,而是通过一个 mergeStrategy 映射表描述每条路径的行为。例如:
const mergeStrategy = {
'colors': 'deepMerge',
'typography': 'deepMerge',
'fonts.families': 'concat',
'id': 'preserve',
'metadata': 'override' // 默认 fallback
};
</font>
<p>实现一个 <code>getStrategy(path)</code> 函数,支持点号路径匹配(可用 <code>path.split('.')</code> + 逐级查找通配符如 <code>'fonts.*'</code>)。</p>
<H3>封装递归合并函数,桥接 Object.assign</H3>
<p>写一个 <code>smartMerge(target, source, strategyMap, path = '')</code>,在需要深合并时递归调用,其余情况交由 Object.assign 或自定义逻辑处理:</p>
<ul>
<li>若当前路径策略为 <code>'deepMerge'</code> 且 target/source 均为对象 → 递归合并各 key;</li>
<li>若策略为 <code>'concat'</code> 且双方为数组 → 合并去重或直接拼接;</li>
<li>若策略为 <code>'preserve'</code> → 跳过该字段,不修改 target;</li>
<li>其他情况(包括 <code>'override'</code>)→ 等效于 <code>Object.assign(target, source)</code> 对当前层级生效。</li>
</ul>
<p>注意:Object.assign 仍用于单层对象的快速赋值(如顶层键合并或 deepMerge 中的当前层 key 遍历),它不是被抛弃,而是被“调度”。</p>
<H3>构建主题引擎类,支持动态加载与运行时切换</H3>
<p>将策略、基础主题、扩展主题封装为可组合实例:</p>
<font color="#666">
<pre class="brush:php;toolbar:false;">
class ThemeEngine {
constructor(baseTheme, strategyMap) {
this.base = baseTheme;
this.strategy = strategyMap;
}
extend(overlay) {
const merged = {};
// 先浅拷贝 base(避免污染)
Object.assign(merged, this.base);
// 再按策略深合并 overlay
smartMerge(merged, overlay, this.strategy);
return merged;
}
use(themeName) {
this.current = this.extend(themes[themeName]);
}
}
这样就能支持:engine.extend(darkTheme).extend(highContrast),每一层都按路径策略精准合并,而非简单 Object.assign 链式调用导致的浅覆盖丢失嵌套结构。

















