JavaScript - 数字数据与NaN

时间:2011-02-24 13:21:51

标签: javascript jquery numeric

我确定我违反了一些深层的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>

4 个答案:

答案 0 :(得分:3)

我认为真正的问题出现在您的循环中:您正在从0循环到rows 包含。因此,如果您为10传递rows,那么您将循环播放11次,从0开始并继续(包括)10。我怀疑这是你真正的问题。如果您没有quantity0元素,或者(假设rows10)您没有quantity10元素,则$("#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));
        }
    }
}

答案 1 :(得分:3)

问题是您在使用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)解决此问题。

答案 2 :(得分:1)

进行一些错误检查:

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瞬间。

答案 3 :(得分:0)

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

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);
}
...