如何在拼接三个字符串之一时避免代码重复?
简化JavaScript冗余字符串拼接代码
我遇到了以下冗余的代码模式:
// 仅定义一次 const articleComponents = { header: "", sections: [], // {title: string, content: string}[] footer: "" }; // ... function appendSuffix(suffix) { if (/* 目标为header */) { if (!articleComponents.header.endsWith(" ")) { articleComponents.header += " "; } articleComponents.header += suffix; } else if (/* 目标为body */) { if (!articleComponents.sections[articleComponents.sections.length - 1].content.endsWith(" ")) { articleComponents.sections[articleComponents.sections.length - 1].content += " "; } articleComponents.sections[articleComponents.sections.length - 1].content += suffix; } else if (/* 目标为footer */) { if (!articleComponents.footer.endsWith(" ")) { articleComponents.footer += " "; } articleComponents.footer += suffix; } }
这段代码存在明显冗余,但由于JavaScript字符串的不可变性,直接像C++那样用引用简化有难度。
优化目标
- 每个条件分支中,目标属性的长表达式仅出现一次
- 不能修改
articleComponents的现有结构,仅允许在appendSuffix内部使用辅助对象或逻辑
C++参考实现
为便于理解,以下是我用C++实现的简化版本:
void appendSuffix(string_view suffix) { string &target = /* 目标为header */ ? articleComponents.header : /* 目标为body */ ? articleComponents.back().content : /* 目标为footer */ ? articleComponents.footer : throw ...; if (target.back() != ' ') { target += ' '; } target += suffix; }
JavaScript实现方案
JavaScript中没有值类型的直接引用,但可以通过保存目标属性的所属对象和属性名来间接实现类似逻辑,避免重复书写长表达式:
方案1:条件分支绑定目标对象与属性
function appendSuffix(suffix) { let targetObj, targetKey; if (/* 目标为header */) { targetObj = articleComponents; targetKey = 'header'; } else if (/* 目标为body */) { // 注意:确保sections不为空,可根据实际情况添加判断 targetObj = articleComponents.sections[articleComponents.sections.length - 1]; targetKey = 'content'; } else if (/* 目标为footer */) { targetObj = articleComponents; targetKey = 'footer'; } else { throw new Error('无效的目标类型'); } // 统一处理字符串拼接逻辑 let currentValue = targetObj[targetKey]; if (!currentValue.endsWith(' ')) { currentValue += ' '; } targetObj[targetKey] = currentValue + suffix; }
方案2:三元表达式简化目标绑定
如果想更贴近C++的简洁写法,可以用三元表达式直接返回目标对象和属性名的数组:
function appendSuffix(suffix) { // 用立即执行函数处理异常分支 const [targetObj, targetKey] = /* 目标为header */ ? [articleComponents, 'header'] : /* 目标为body */ ? [articleComponents.sections.at(-1), 'content'] : // 使用at(-1)更简洁获取最后一项 /* 目标为footer */ ? [articleComponents, 'footer'] : (() => { throw new Error('无效的目标类型'); })(); let currentValue = targetObj[targetKey]; if (!currentValue.endsWith(' ')) { currentValue += ' '; } targetObj[targetKey] = currentValue + suffix; }
说明
由于JavaScript字符串是不可变值类型,我们无法直接获取其引用修改原变量,但通过绑定目标属性的宿主对象和属性名,可以先读取值、处理后再赋值回原属性,既避免了重复代码,又符合原结构的依赖要求。
内容的提问来源于stack exchange,提问作者Jan Schultke
相关产品推荐
相关产品推荐

