JavaScript新增减法switch分支运行返回undefined问题求解
问题背景
- 开发自然语言识别小程序,优先实现数学运算能力
- 已支持加法运算,新增减法分支时,输入
subtract 2 from 5返回undefined,预期返回-3 - 原有核心逻辑通过switch匹配操作符,加法分支代码如下:
switch (operator) { case "add": return numbers.reduce((a, b) => Number(a) + Number(b));
- 问题复现代码:
function output(func) { console.log(func) } function read(str) { const dl = str.split(' '); const operator = dl.shift(x => x.includes("add", "sub", "mul", "div")) const numbers = dl.filter(x => Number(x)) switch (operator) { case "add": return numbers.reduce((a, b) => Number(a) + Number(b)); case "subtract": return numbers.reduce((a, b) => Number(a) - Number(b)); } } const result = read( "add 6 and 4" ) output(result)
错误原因
Array.shift()本身不接受回调参数,方法签名为shift(),无任何入参,传入的函数会被直接忽略,永远只返回数组的第一个元素。一旦输入的操作符不在句首,就无法匹配到switch分支,直接返回undefined。- 数字提取逻辑有漏洞:
x => Number(x)的判断规则是把转换后的值转布尔值,Number(0)结果为0,属于falsy值,会被错误过滤,后续遇到含0的运算必然出错。 - 操作符匹配逻辑无效:
String.includes()方法的第二个参数是搜索起始位置,不支持传入多个关键词做批量匹配,写的多关键词判断逻辑本身就不成立。
修复后代码
直接替换替换原有read相关逻辑即可,已兼容提到的减法场景,同时预留了乘除运算扩展能力:
function output(func) { console.log(func) } // 操作符和对应运算逻辑映射,后续新增运算直接加配置即可 const operationHandlers = { add: nums => nums.reduce((a, b) => a + b), subtract: nums => nums.reduce((a, b) => a - b), multiply: nums => nums.reduce((a, b) => a * b), mul: nums => operationHandlers.multiply(nums), divide: nums => nums.reduce((a, b) => a / b), div: nums => operationHandlers.divide(nums) } function read(str) { const words = str.split(' '); let operator = null; let opPosition = -1; // 遍历分词结果定位操作符,不依赖操作符必须在句首 for (let i = 0; i < words.length; i++) { const currentWord = words[i].toLowerCase(); if (Object.keys(operationHandlers).includes(currentWord)) { operator = currentWord; opPosition = i; break; } } if (!operator) return; // 提取操作符之后的所有有效数字,修复0被过滤的问题 const numbers = words .slice(opPosition + 1) .filter(item => !isNaN(Number(item))) .map(Number); return operationHandlers[operator](numbers); } // 测试验证 output(read("add 6 and 4")); // 10 output(read("subtract 2 from 5")); // -3,符合预期
补充说明
如果后续需要符合自然语言的减法语义(即subtract 2 from 5返回3),只需要调整subtract对应的处理函数,识别到from关键词时调换数字顺序即可,当前代码结构不需要大改。
内容的提问来源于stack exchange,提问作者1BL1ZZARD
相关产品推荐
相关产品推荐

