Typescript代码优化:如何根据浏览器语言偏好匹配应用支持语言
问题原因梳理
- lambda写法返回空的原因:
forEach方法设计上没有返回值,回调函数内的return只会终止当前回调的执行,不会中断遍历,也不会把返回值传递给外层变量,因此最终拿到的永远是undefined。 - 函数移入类后测试不通过的原因:大概率是测试环境没有模拟浏览器全局对象
navigator,类方法直接依赖全局属性导致执行报错。
优化方案
方案1:内联lambda写法(仅调用一次时使用)
用Array.prototype.find替代forEach,实现匹配到第一个符合条件的语言就终止遍历,逻辑和原代码完全等价:
@Component export default class Foo extends Vue { ... created() { // 直接内联实现,不需要单独定义函数 const supportedLangs = ['en', 'es'] as const const lang = navigator.languages.find(lang => supportedLangs.some(supLang => lang.startsWith(supLang)) )?.slice(0, 2) ?? 'en' ... } ... }
如果后续需要新增支持的语言,只需要往supportedLangs数组里加值即可,不需要修改判断逻辑。
方案2:移入类内部方法(解决测试不通过问题)
给方法增加可选的入参,默认值取navigator.languages,测试时可以直接传入模拟的语言数组,不需要依赖全局浏览器环境:
@Component export default class Foo extends Vue { ... created() { const lang = this.findLang() ... } // 入参支持传入自定义语言列表,测试时直接传模拟值即可 private findLang(customLangs = navigator.languages): string { const supportedLangs = ['en', 'es'] as const return customLangs.find(lang => supportedLangs.some(supLang => lang.startsWith(supLang)) )?.slice(0, 2) ?? 'en' } ... }
测试用例示例:
// 不需要模拟全局navigator,直接传参测试 const component = new Foo() expect(component.findLang(['es-AR', 'zh-CN'])).toBe('es') expect(component.findLang(['fr-FR', 'de-DE'])).toBe('en')
内容的提问来源于stack exchange,提问作者vic
相关产品推荐
相关产品推荐

