JavaScript - 数字数据与 NaN

发布于 2024-10-19 10:25:36 字数 2808 浏览 1 评论 0原文

我确信我违反了 javascript 的一些深刻的黑暗法则,但我并不是真正的 JS 开发人员,这让我发疯。在订单上调用此函数来逐行读取商品的数量和价格,然后提供小计、交货和总计。

问题出在第 10 行 - 它一直“忘记”整个变量数据是数字(浮点),因此返回大量 NaN。如何强制整个函数中的变量表现为数字而不是字符串?

编辑

这是根据迄今为止的反馈修改后的代码(谢谢!)。它仍然不起作用;)

<script type="text/javascript">
function subTotal(rows) {
    var i, subTotal, lineTotal, orderShip, orderTotal;
    for (i = 1; i <= rows; ++i) {
        //Grab values from form
        var quantity = parseFloat($('#quantity' + i).val());
        var uPrice = parseFloat($('#uPrice' + i).val());

        //Error checking
        alert('quantity = ' + quantity +' and uPrice = ' + uPrice);
        if (isNaN(quantity)) alert('quantity = NaN');
        if (isNaN(uPrice)) alert('uPrice = NaN');

        if ((quantity == '') || (uPrice == '')) {
        } else {
            lineTotal = quantity * uPrice;
            alert('lineTotal = ' + lineTotal);
            subTotal += lineTotal;
            alert('subTotal = ' + subTotal);
        }
        //If we've maxed out the number of rows, then subTotal should be calculated - push back to form.
        if (i == rows) { 
            $('#orderSubTotal').val(subTotal );
            orderShip = subTotal * 0.25;
            $('#orderShip').val(orderShip.toFixed(2));
            orderTotal = subTotal + orderShip;
            $('#orderTotal').val(orderTotal.toFixed(2));
        }
    }
}
</script>

<form>
<table>
<tr>
    <td><input type="text" id="item1" name="item1" value="Some description" readonly="readonly" /></td>
    <td><input type="text" id="quantity1" name="quantity1" value="25" onchange="javascript:subTotal('2')" /></td>
    <td><input type="text" id="uPrice1" name="uPrice1" value="1.50" readonly="readonly" /></td>    
</tr>
<tr>
    <td><input type="text" id="item2" name="item2" value="Some description" readonly="readonly" /></td>
    <td><input type="text" id="quantity2" name="quantity2" value="25" onchange="javascript:subTotal('2')" /></td>
    <td><input type="text" id="uPrice2" name="uPrice2" value="2.75" readonly="readonly" /></td>    
</tr>
<tr>
    <td colspan="3">
      SubTotal 
      <input type="text" id="orderSubTotal" name="orderSubTotal" readonly="readonly" style="text-align: right" value="0.00" />
      <br />Shipping 
      <input type="text" id="orderShip" name="orderShip" readonly="readonly" style="text-align: right" value="0.00" />
      <br />Total 
      <input type="text" id="orderTotal" name="orderTotal" readonly="readonly" style="text-align: right" value="0.00" />    
    </td>  
</tr>
</table>
</form>

I'm sure I'm contravening some deep dark law of javascript, but I'm not really a JS developer and this is driving me mad. This function is called on an orderform to read the quantity and price of items, row by row, and then provide the subtotal, delivery and total.

The problem is with line 10 - it keeps "forgetting" that the variable data throughout is numeric (floating point) and so returns lots of NaN. How can I force the variables throughout this function to behave as numbers rather than strings?

EDIT

Here's the revised code based on feedback so far (thank you!). It's still not working ;)

<script type="text/javascript">
function subTotal(rows) {
    var i, subTotal, lineTotal, orderShip, orderTotal;
    for (i = 1; i <= rows; ++i) {
        //Grab values from form
        var quantity = parseFloat($('#quantity' + i).val());
        var uPrice = parseFloat($('#uPrice' + i).val());

        //Error checking
        alert('quantity = ' + quantity +' and uPrice = ' + uPrice);
        if (isNaN(quantity)) alert('quantity = NaN');
        if (isNaN(uPrice)) alert('uPrice = NaN');

        if ((quantity == '') || (uPrice == '')) {
        } else {
            lineTotal = quantity * uPrice;
            alert('lineTotal = ' + lineTotal);
            subTotal += lineTotal;
            alert('subTotal = ' + subTotal);
        }
        //If we've maxed out the number of rows, then subTotal should be calculated - push back to form.
        if (i == rows) { 
            $('#orderSubTotal').val(subTotal );
            orderShip = subTotal * 0.25;
            $('#orderShip').val(orderShip.toFixed(2));
            orderTotal = subTotal + orderShip;
            $('#orderTotal').val(orderTotal.toFixed(2));
        }
    }
}
</script>

<form>
<table>
<tr>
    <td><input type="text" id="item1" name="item1" value="Some description" readonly="readonly" /></td>
    <td><input type="text" id="quantity1" name="quantity1" value="25" onchange="javascript:subTotal('2')" /></td>
    <td><input type="text" id="uPrice1" name="uPrice1" value="1.50" readonly="readonly" /></td>    
</tr>
<tr>
    <td><input type="text" id="item2" name="item2" value="Some description" readonly="readonly" /></td>
    <td><input type="text" id="quantity2" name="quantity2" value="25" onchange="javascript:subTotal('2')" /></td>
    <td><input type="text" id="uPrice2" name="uPrice2" value="2.75" readonly="readonly" /></td>    
</tr>
<tr>
    <td colspan="3">
      SubTotal 
      <input type="text" id="orderSubTotal" name="orderSubTotal" readonly="readonly" style="text-align: right" value="0.00" />
      <br />Shipping 
      <input type="text" id="orderShip" name="orderShip" readonly="readonly" style="text-align: right" value="0.00" />
      <br />Total 
      <input type="text" id="orderTotal" name="orderTotal" readonly="readonly" style="text-align: right" value="0.00" />    
    </td>  
</tr>
</table>
</form>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

爱冒险 2024-10-26 10:25:36

我认为真正问题出在您的循环中:您从0循环到包含。因此,如果您为 rows 传入 10,则将循环 11 次,从 0 开始,一直到(包括)10..我怀疑这才是你真正的问题。如果您没有 quantity0 元素,或者(假设 rows10),则您没有 quantity10 code> 元素,那么 $("#quantity" + i).val() 将返回 undefined,转换时会转换为 NaN它(隐式或显式)。 (uPrice0 / uPrice10 也是如此。)当然,一旦有了 NaN任何 数学运算使用它会导致 NaN

至于你关于如何确保它们不改变的问题,基本上,尽早将它们转换为数字。您当前正在使用 quantityuPrice 而不进行转换,这意味着它们最初是字符串。现在,JavaScript 可以非常智能地为您转换它们,但有时您想要明确地进行转换。

另外:x 从哪里来?

您还没有显示任何可供使用的数据,而只是推测:

function subTotal(rows) {
    var i, subTotal, lineTotal, quantity, uPrice, orderShip, orderTotal;

    subTotal = 0;
    for (i = 0; i < rows; ++i) {
    // OR
    //for (i = 1; i <= rows; ++i) {
        quantity = $('#quantity' + i).val();
        uPrice = $('#uPrice' + i).val();
        if ((quantity == '') || (uPrice == '')) {
        } else {
            quantity = parseFloat(quantity);
            uPrice   = parseFloat(uPrice);
            // Might consider checking isNaN(quantity) and isNan(uPrice) here
            lineTotal = quantity * uPrice;
            subTotal += lineTotal;
            alert('subtotal = ' + subTotal);
        }
        if (i == x) {                           // Where does `x` come from?
            $('#orderSubTotal').val(subTotal );
            orderShip = subTotal * 0.25;
            $('#orderShip').val(orderShip.toFixed(2));
            orderTotal = subTotal + orderShip;
            $('#orderTotal').val(orderTotal.toFixed(2));
        }
    }
}

I think the real problem is in your loop: You're looping from 0 to rows inclusive. So if you pass in 10 for rows, you'll be looping 11 times, starting with 0 and continuing through (including) 10. I suspect that's your real problem. If you don't have a quantity0 element, or (assuming rows is 10) you don't have a quantity10 element, then $("#quantity" + i).val() will return undefined, which converts to NaN when you convert it (implicitly or explicitly). (And the same for uPrice0 / uPrice10.) And of course, once you have NaN, any mathematical operation using it results in NaN.

In terms of your question about how to ensure they don't change, basically, convert them to numbers early. You're currently using quantity and uPrice without converting them, which means initially they're strings. Now, JavaScript is pretty smart about converting them for you, but sometimes you want to be explicit.

Separately: Where does x come from?

You haven't shown any data to work with, but just speculatively:

function subTotal(rows) {
    var i, subTotal, lineTotal, quantity, uPrice, orderShip, orderTotal;

    subTotal = 0;
    for (i = 0; i < rows; ++i) {
    // OR
    //for (i = 1; i <= rows; ++i) {
        quantity = $('#quantity' + i).val();
        uPrice = $('#uPrice' + i).val();
        if ((quantity == '') || (uPrice == '')) {
        } else {
            quantity = parseFloat(quantity);
            uPrice   = parseFloat(uPrice);
            // Might consider checking isNaN(quantity) and isNan(uPrice) here
            lineTotal = quantity * uPrice;
            subTotal += lineTotal;
            alert('subtotal = ' + subTotal);
        }
        if (i == x) {                           // Where does `x` come from?
            $('#orderSubTotal').val(subTotal );
            orderShip = subTotal * 0.25;
            $('#orderShip').val(orderShip.toFixed(2));
            orderTotal = subTotal + orderShip;
            $('#orderTotal').val(orderTotal.toFixed(2));
        }
    }
}
流星番茄 2024-10-26 10:25:36

问题在于,您在使用 parseFloat 之前对字段执行数学计算:

var lineTotal = quantity * uPrice;   // <-- result is most likely NaN here
subTotal = parseFloat(subTotal ) + parseFloat(lineTotal);

在获得值时执行解析,以使生活变得更轻松:

    var quantity = parseFloat($('#quantity' + i).val());
    var uPrice = parseFloat($('#uPrice' + i).val());

然后更改 subTotal = 行:

        subTotal += lineTotal;

另一个可能的问题是,如果 $('#uPrice' + i).val() 的结果不是以可解析的浮点开头 — 如果它以货币符号,例如 £$parseFloat 将始终为该字段返回 NaN。您可以使用 $('#uPrice' + i).val().slice(1) 解决此问题。

The problem is that you're performing a mathematical calculation on the fields before using parseFloat:

var lineTotal = quantity * uPrice;   // <-- result is most likely NaN here
subTotal = parseFloat(subTotal ) + parseFloat(lineTotal);

Perform your parsing at the point you get the values to make life a little easier:

    var quantity = parseFloat($('#quantity' + i).val());
    var uPrice = parseFloat($('#uPrice' + i).val());

Then change the subTotal = line to this:

        subTotal += lineTotal;

Another possible issue is if the result of $('#uPrice' + i).val() doesn't start with a parseable float — if it starts with a currency symbol, e.g. £ or $, for instance — parseFloat will always return NaN for that field. You can work around it using $('#uPrice' + i).val().slice(1).

久而酒知 2024-10-26 10:25:36

进行一些错误检查:

function subTotal(rows) {
    var subTotal = 0;
    while (var i=0; i < rows; i++) {
        // convert as soon as you get the values
        var quantity = parseFloat($('#quantity' + i).val());
        var uPrice = parseFloat($('#uPrice' + i).val());
        if (isNaN(quantity) || isNaN(uPrice)) { // error checking
            alert("Invalid values on row " + i);
            continue;
        }
        var lineTotal = quantity * uPrice;
        subTotal += lineTotal;
        alert('subtotal = ' + subTotal);
        if (i == x) {
            $('#orderSubTotal').val(subTotal );
            var orderShip = subTotal * 0.25;
            $('#orderShip').val(orderShip.toFixed(2));
            var orderTotal = subTotal + orderShip;
            $('#orderTotal').val(orderTotal.toFixed(2));
        }
    }
}

您可能在某个时候遇到索引问题,从其中一个(不存在的字段)获取 NaN,并将其添加到 subTotal这使得它立即成为 NaN

Do some error checking:

function subTotal(rows) {
    var subTotal = 0;
    while (var i=0; i < rows; i++) {
        // convert as soon as you get the values
        var quantity = parseFloat($('#quantity' + i).val());
        var uPrice = parseFloat($('#uPrice' + i).val());
        if (isNaN(quantity) || isNaN(uPrice)) { // error checking
            alert("Invalid values on row " + i);
            continue;
        }
        var lineTotal = quantity * uPrice;
        subTotal += lineTotal;
        alert('subtotal = ' + subTotal);
        if (i == x) {
            $('#orderSubTotal').val(subTotal );
            var orderShip = subTotal * 0.25;
            $('#orderShip').val(orderShip.toFixed(2));
            var orderTotal = subTotal + orderShip;
            $('#orderTotal').val(orderTotal.toFixed(2));
        }
    }
}

You're probably running into an index problem at some point, getting a NaN from one of the (non-existing fields), adding it to subTotal which makes it a NaN instantly.

丑丑阿 2024-10-26 10:25:36

最好在进行任何数学运算之前转换该值。所以代码应该是:

var numQuanitity = parseFloat(quantity);
var numPrice = parseFloat(uPrice);
if (isNaN(numQuanitity) || isNaN(numPrice)) {
   //you can alert or ignore
}
else {
   var lineTotal = numQuanitity * numPrice;
   subTotal += lineTotal;
   alert('subtotal = ' + subTotal);
}
...

You better convert the value before doing any mathematical operation. So the code should be:

var numQuanitity = parseFloat(quantity);
var numPrice = parseFloat(uPrice);
if (isNaN(numQuanitity) || isNaN(numPrice)) {
   //you can alert or ignore
}
else {
   var lineTotal = numQuanitity * numPrice;
   subTotal += lineTotal;
   alert('subtotal = ' + subTotal);
}
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文