Thunderbird扩展开发中如何减少JS偏好封装函数的重复代码?
核心结论
原有写法存在大量重复逻辑,可维护性差,新增配置类型时需要反复复制相似代码,非常容易出错,完全可以优化。以下是符合ES6规范的优化方案:
优化方案1:工厂函数动态生成方法(兼容原有调用逻辑,无侵入)
这个方案的优势是原有调用getCharPref/setIntPref的代码完全不需要修改,仅调整Pref对象的实现即可,对老项目非常友好。
MyGlobalObject.Prefs = { preferencePrefix: "extensions.myextname.", } // 定义支持的偏好类型,新增类型仅需在此数组中加项即可 const PREF_TYPES = ['Char', 'Int', 'Bool'] PREF_TYPES.forEach(type => { // 自动生成对应类型的get方法 MyGlobalObject.Prefs[`get${type}Pref`] = function(prefName, defaultValue) { try { return Services.prefs[`get${type}Pref`]( `${this.preferencePrefix}${prefName}` ) } catch (ex) { if (defaultValue !== undefined) return defaultValue #ifdef DEBUG console.log(`Failed obtaining ${type.toLowerCase()} preference ${prefName}`) #endif throw ex } } // 自动生成对应类型的set方法 MyGlobalObject.Prefs[`set${type}Pref`] = function(prefName, val) { Services.prefs[`set${type}Pref`]( `${this.preferencePrefix}${prefName}`, val ) } })
该方案的特点:
- 完全兼容原有API,老代码无改动成本
- 逻辑统一收敛,后续调整公共规则(比如前缀生成逻辑、错误处理逻辑)仅需修改一处
- 新增配置类型不需要重复编写模板代码,维护成本极低
优化方案2:Proxy封装实现更简洁的调用(适合可调整调用逻辑的场景)
如果可以调整现有调用方式,不需要保留原有的get/set方法调用格式,还可以用ES6 Proxy实现更直观的属性式读写:
const preferencePrefix = "extensions.myextname." MyGlobalObject.Prefs = new Proxy({}, { get(target, prop) { const fullKey = `${preferencePrefix}${prop}` const prefType = Services.prefs.getPrefType(fullKey) switch(prefType) { case Services.prefs.PREF_STRING: return Services.prefs.getCharPref(fullKey) case Services.prefs.PREF_INT: return Services.prefs.getIntPref(fullKey) case Services.prefs.PREF_BOOL: return Services.prefs.getBoolPref(fullKey) default: // 不存在的配置可根据需求返回默认值或抛出错误 return undefined } }, set(target, prop, value) { const fullKey = `${preferencePrefix}${prop}` switch(typeof value) { case 'string': Services.prefs.setCharPref(fullKey, value) return true case 'number': Services.prefs.setIntPref(fullKey, value) return true case 'boolean': Services.prefs.setBoolPref(fullKey, value) return true default: throw new Error(`不支持的配置值类型:${typeof value}`) } } })
调用方式可以简化为:
// 读取配置 const userName = MyGlobalObject.Prefs.userName // 写入配置 MyGlobalObject.Prefs.port = 8080
该方案的特点是调用更简洁,不需要记忆各类get/set方法名,缺点是不兼容原有调用逻辑,需要全量修改历史调用代码。
如果你的项目规模极小,且后续没有新增配置类型的需求,原有写法也可以正常运行,但从长期可维护性角度,还是建议做优化,避免后续复制代码时出现人为错误。
内容的提问来源于stack exchange,提问作者einpoklum
相关产品推荐
相关产品推荐

