为什么JS数组typeof返回object而非数值导致LCM计算得NaN
问题根因
你遇到的两个现象原因非常明确:
typeof检测数组返回object是JavaScript的标准设计,数组属于特殊对象类型,这不是bug,和你返回NaN的问题没有关系- 最终计算得到NaN有三个直接诱因:
- 从DOM输入框拿到的
x、y默认是字符串类型,你调用.toFixed(2)把所有计算出的倍数转成了字符串存入数组,Math.min无法直接对字符串值做数值比较 Math.min接收逗号分隔的数值参数,不支持直接传入单个数组作为参数- 你只枚举了两个数前10倍的数值,大部分场景下最小公倍数不在这个范围内,会导致交集数组为空,空值参与计算直接返回NaN
- 额外冗余问题:循环里写的
if (i === 11) { break; }是永远不会执行的死代码,因为循环条件是i < 11,i最大取到10,这个判断可以直接删除。
- 从DOM输入框拿到的
修复后代码
function myFunction(){ // 输入值直接转数值类型,从源头避免类型问题 const x = Number(document.getElementById("int").value); let textx = ""; let multiplex = []; const y = Number(document.getElementById("int1").value); let texty = ""; let multipley = []; let result = ""; // 提前做输入校验,不合法直接返回 if(Number.isNaN(x)){ window.alert(`Please input a number. ${x} is not a valid number`); return; } if(Number.isNaN(y)){ window.alert(`Please input a number. ${y} is not a valid number`); return; } // 枚举倍数到x*y即可,两个数的乘积一定是它们的公倍数,不会漏判 const maxRange = x * y; for (let i = 1; i <= maxRange; i++) { multiplex.push(i * x); } for (let i = 1; i <= maxRange; i++) { multipley.push(i * y); } // 拼接展示文本时再做格式化,数组里全程存数值类型 textx = `${multiplex.map(item => item.toFixed(2)).join(', ')} are the multiples of ${x}`; texty = `${multipley.map(item => item.toFixed(2)).join(', ')} are the multiples of ${y}`; document.getElementById("demo").innerHTML = textx; document.getElementById("demo1").innerHTML = texty; // 用展开运算符把数组拆成参数列表传给Math.min,直接计算数值结果 const commonMultiples = multiplex.filter(value => multipley.includes(value)); const lcmResult = Math.min(...commonMultiples); // 普通日志打印用console.log,console.group是日志分组方法,不适合打普通变量 console.log(typeof multiplex, typeof multipley); // 正常返回object,无需处理 console.log(lcmResult); result = `${lcmResult} is the Least Common Multiple (LCM)`; document.getElementById('result').innerHTML = result; }
优化建议
枚举倍数找LCM的实现效率很低,尤其是数值大的时候会生成很长的数组。更高效的实现是用最大公约数(GCD)公式计算:LCM(a,b) = Math.abs(a*b) / GCD(a,b),GCD可以用欧几里得算法快速实现,不需要遍历枚举。
内容的提问来源于stack exchange,提问作者Sami Khan
相关产品推荐
相关产品推荐

