JavaScript向HTML传递随机数时出现数值异常的问题排查
随机数超出预期范围的原因分析
问题场景
你希望实现:当Level输入框的值变化时,生成该值±50%范围内的随机数填充到Attribute输入框,但实际操作中输入10却得到72这类超出范围的数值,单独调用随机数函数却正常。
你的HTML代码:
<!DOCTYPE html> <html> <body> <input type = "number" name = "playerLevel" onchange = "populateAttributes()" id = "playerLevel"> <label for = "playerLevel">Level</label> </body> <br> <tr> <td><input type = "number" id = "attributeScore"></td> <label for = "attribute">Attribute</label> </tr> <script src = "script.js"></script> </html>
对应的JavaScript代码:
function generateRandomLevel(targetLevel) { const target = targetLevel; // The target around which the random levels are generated const range = 0.5; // 0.5 => 50% deviation from target and so on const upperLevelLimit = Math.round(target + target * range); // Target + 50% deviation const lowerLevelLimit = Math.round(target - target * range); // Target - 50% deviation let x = parseInt(Math.random() * (upperLevelLimit - lowerLevelLimit) + lowerLevelLimit); // Generate Level within 50% of target return x; } function populateAttributes() { let y = generateRandomLevel(document.getElementById("playerLevel").value); // Passes the value of "playerLevel" to the random nunber generator document.getElementById("attributeScore").value = y; // Set the value inside "playerLevel" to the random number generated }
异常原因
核心问题是输入框的value属性返回的是字符串类型,而你直接把这个字符串传给了generateRandomLevel函数:
- 当输入10时,
targetLevel是字符串"10" - 执行
target * range时,JavaScript会隐式把字符串转成数字,得到10 * 0.5 = 5 - 但执行
target + target * range时,因为target是字符串,会触发字符串拼接,变成"10" + 5 = "105" - 后续
Math.round("105")虽然会转成数字105,但此时上限变成了105,下限是"10" - 5 = 5 - 最终随机数的范围变成了5到105之间,自然会出现72这类远超预期的数值
而单独调用函数时,你传入的是数字10,所有运算都是数字运算,所以结果正常。
解决方法
只需要在传递输入值时,把字符串转成数字即可,有两种常见方式:
方式1:在调用函数时转换
修改populateAttributes函数:
function populateAttributes() { // 用parseInt把输入值转为整数,或者用Number()转成数字 const level = parseInt(document.getElementById("playerLevel").value); let y = generateRandomLevel(level); document.getElementById("attributeScore").value = y; }
方式2:在随机数函数内部转换
修改generateRandomLevel函数的第一行,确保target是数字:
function generateRandomLevel(targetLevel) { const target = Number(targetLevel); // 强制转为数字类型 const range = 0.5; const upperLevelLimit = Math.round(target + target * range); const lowerLevelLimit = Math.round(target - target * range); let x = parseInt(Math.random() * (upperLevelLimit - lowerLevelLimit) + lowerLevelLimit); return x; }
内容的提问来源于stack exchange,提问作者MDK
相关产品推荐
相关产品推荐

