简体   繁体   English

JavaScript 计算器显示 NaN

[英]JavaScript calculator displays NaN

Trying to make a simple javascript calculator and having a problem, when pushing a button and activate function console reflect NaN.尝试制作一个简单的 javascript 计算器并遇到问题,在按下按钮并激活功能控制台时会反映 NaN。 Cannot figure out whats a problem.Function somehow working is not right.无法弄清楚什么是问题。功能以某种方式工作是不正确的。 Code is in snippet.代码在片段中。

 window.onload = function() { var screen = document.getElementById("screen"); var keys = document.getElementsByClassName("keys"); var span = document.getElementsByTagName("span"); (function() { for (var i = 0; i < span.length; i++) { span[i].onclick = theCode; } function theCode() { var operators = ['+', '-', '/', '*']; var btnVal = this.innerHTML; var srnVal = screen.innerHTML; var opers = { '*': function(num) { return (num[0] * num[1]) }, '+': function(num) { return (num[0] + num[1]) }, '-': function(num) { return (num[0] - num[1]) }, '/': function(num) { return (num[0] / num[1]) } } var detectOp = function(value) { for (var i = 0; i < operators.length; i++) { if (operators[i] == value) { return true; } } return false; }; function iteration(num) { num = num + ''; for (var i = num.indexOf - 1; i > srnVal.length; i--) { num = srnVal[i] + num; return num; } for (var j = num.indexOf + 1; j < srnVal.length; j++) { num = num + srnVal[j]; return num; } return parseInt(num); } if (btnVal == '=') { for (var i = 0; i < srnVal.length; i++) { if (detectOp(srnVal[i])) { screen.innerHTML = opers[srnVal[i]](iteration); } } } else { srnVal += btnVal; screen.innerHTML += btnVal; } } })(); };
 /* Basic reset */ * { margin: 0; padding: 0; box-sizing: border-box; /* Better text styling */ font: bold 14px Arial, sans-serif; } /* Finally adding some IE9 fallbacks for gradients to finish things up */ /* A nice BG gradient */ html { height: 100%; background: white; background: radial-gradient(circle, #fff 20%, #ccc); background-size: cover; } /* Using box shadows to create 3D effects */ #calculator { width: 325px; height: auto; margin: 100px auto; padding: 20px 20px 9px; background: #9dd2ea; background: linear-gradient(#9dd2ea, #8bceec); border-radius: 3px; box-shadow: 0px 4px #009de4, 0px 10px 15px rgba(0, 0, 0, 0.2); } /* Top portion */ .top span.clear { float: left; } /* Inset shadow on the screen to create indent */ .top #screen { height: 40px; width: 212px; float: right; padding: 0 10px; background: rgba(0, 0, 0, 0.2); border-radius: 3px; box-shadow: inset 0px 4px rgba(0, 0, 0, 0.2); /* Typography */ font-size: 17px; line-height: 40px; color: white; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); text-align: right; letter-spacing: 1px; } /* Clear floats */ .keys, .top { overflow: hidden; } /* Applying same to the keys */ .keys span, .top span.clear { float: left; position: relative; top: 0; cursor: pointer; width: 66px; height: 36px; background: white; border-radius: 3px; box-shadow: 0px 4px rgba(0, 0, 0, 0.2); margin: 0 7px 11px 0; color: #888; line-height: 36px; text-align: center; /* prevent selection of text inside keys */ user-select: none; /* Smoothing out hover and active states using css3 transitions */ transition: all 0.2s ease; } /* Remove right margins from operator keys */ /* style different type of keys (operators/evaluate/clear) differently */ .keys span.operator { background: #FFF0F5; margin-right: 0; } .keys span.eval { background: #f1ff92; box-shadow: 0px 4px #9da853; color: #888e5f; } .top span.clear { background: #ff9fa8; box-shadow: 0px 4px #ff7c87; color: white; } /* Some hover effects */ .keys span:hover { background: #9c89f6; box-shadow: 0px 4px #6b54d3; color: white; } .keys span.eval:hover { background: #abb850; box-shadow: 0px 4px #717a33; color: #ffffff; } .top span.clear:hover { background: #f68991; box-shadow: 0px 4px #d3545d; color: white; } /* Simulating "pressed" effect on active state of the keys by removing the box-shadow and moving the keys down a bit */ .keys span:active { box-shadow: 0px 0px #6b54d3; top: 4px; } .keys span.eval:active { box-shadow: 0px 0px #717a33; top: 4px; } .top span.clear:active { top: 4px; box-shadow: 0px 0px #d3545d; }
 <DOCTYPE html> <html> <head> </head> <body> <div id="calculator"> <!-- Screen and clear key --> <div class="top"> <span class="clear">C</span> <div id="screen"></div> </div> <div class="keys"> <!-- operators and other keys --> <span value="7">7</span> <span value="8">8</span> <span value="9">9</span> <span class="operator" value="+">+</span> <span value="4">4</span> <span value="5">5</span> <span value="6">6</span> <span class="operator" value="-">-</span> <span value="1">1</span> <span value="2">2</span> <span value="3">3</span> <span class="operator" value="/">/</span> <span value="0">0</span> <span>.</span> <span class="eval" value="=">=</span> <span class="operator" value="*">*</span> </div> </div> </body>

It's hard to answer without more detail - but NaN (not a number) may imply that your calculator is trying to perform numerical operations on a non number.没有更多细节很难回答 - 但 NaN(不是数字)可能暗示您的计算器正在尝试对非数字执行数字运算。

To resolve, you can wrap number variables in parseFloat(), ie要解决,您可以在 parseFloat() 中包装数字变量,即

var number = document.getElementById("inputBox1").value;

becomes变成

var number = parseFloat(document.getElementById("inputBox1").value);

Edit:编辑:

Based on the code you provided, I think applying my fix to some of the innerHTML pulls your doing should work.根据您提供的代码,我认为将我的修复应用于您所做的一些 innerHTML 拉动应该有效。

Your problem lies in the line你的问题在于线

screen.innerHTML = opers[srnVal[i]](iteration);

You're properly fetching your operation function with opers[srnVal[i]] but then you invoke it while giving it a function as argument when it's expecting an array or 2 numbers.您正在使用opers[srnVal[i]]正确获取您的操作函数,但是当它需要一个数组或 2 个数字时,您会在给它一个函数作为参数的同时调用它。 You end up attempting a numerical operation with undefined , which gives you NaN .您最终尝试使用undefined进行数值运算,这会给您NaN

This is the part you need to fix.这是您需要修复的部分。

Edit: I'm really not sure what your iteration function is supposed to be doing, but it looks to me like it's some failing javascript that would generate errors if it came to be executed anyway.编辑:我真的不确定你的iteration函数应该做什么,但在我看来它是一些失败的 javascript,如果它无论如何都会产生错误。 What you need to do here is to parse your expression and evaluate the result.您需要在这里做的是解析您的表达式并评估结果。 I've written a working example, here is the piece of code that makes the evaluation work:我写了一个工作示例,这是使评估工作的一段代码:

if (btnVal == '=') {
    var expression = srnVal.split(''),
            cursor,
            leftHand,
            operation;

    while (expression.length) {
        cursor = expression.shift();
        if (detectOp(cursor)) {
            operation = opers[cursor];
        } else if (operation && leftHand) {
            leftHand = operation([leftHand, parseInt(cursor)]);
            operation = null;
        } else if(leftHand) {
            leftHand = parseInt(leftHand + cursor);
        } else {
            leftHand = parseInt(cursor);
        }
    }
    screen.innerHTML = leftHand;
} else {
    srnVal += btnVal;
    screen.innerHTML += btnVal;
}

 window.onload = function() { var screen = document.getElementById("screen"); var keys = document.getElementsByClassName("keys"); var span = document.getElementsByTagName("span"); (function() { for (var i = 0; i < span.length; i++) { span[i].onclick = theCode; } function theCode() { var operators = ['+', '-', '/', '*']; var btnVal = this.innerHTML; var srnVal = screen.innerHTML; var opers = { '*': function(num) { return (num[0] * num[1]) }, '+': function(num) { return (num[0] + num[1]) }, '-': function(num) { return (num[0] - num[1]) }, '/': function(num) { return (num[0] / num[1]) } } var detectOp = function(value) { for (var i = 0; i < operators.length; i++) { if (operators[i] == value) { return true; } } return false; }; if (btnVal == '=') { var expression = srnVal.split(''), cursor, leftHand, operation; while (expression.length) { cursor = expression.shift(); if (detectOp(cursor)) { operation = opers[cursor]; } else if (operation && leftHand) { leftHand = operation([leftHand, parseInt(cursor)]); operation = null; } else if (leftHand) { leftHand = parseInt(leftHand + cursor); } else { leftHand = parseInt(cursor); } } screen.innerHTML = leftHand; } else { srnVal += btnVal; screen.innerHTML += btnVal; } } })(); };
 /* Basic reset */ * { margin: 0; padding: 0; box-sizing: border-box; /* Better text styling */ font: bold 14px Arial, sans-serif; } /* Finally adding some IE9 fallbacks for gradients to finish things up */ /* A nice BG gradient */ html { height: 100%; background: white; background: radial-gradient(circle, #fff 20%, #ccc); background-size: cover; } /* Using box shadows to create 3D effects */ #calculator { width: 325px; height: auto; margin: 100px auto; padding: 20px 20px 9px; background: #9dd2ea; background: linear-gradient(#9dd2ea, #8bceec); border-radius: 3px; box-shadow: 0px 4px #009de4, 0px 10px 15px rgba(0, 0, 0, 0.2); } /* Top portion */ .top span.clear { float: left; } /* Inset shadow on the screen to create indent */ .top #screen { height: 40px; width: 212px; float: right; padding: 0 10px; background: rgba(0, 0, 0, 0.2); border-radius: 3px; box-shadow: inset 0px 4px rgba(0, 0, 0, 0.2); /* Typography */ font-size: 17px; line-height: 40px; color: white; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); text-align: right; letter-spacing: 1px; } /* Clear floats */ .keys, .top { overflow: hidden; } /* Applying same to the keys */ .keys span, .top span.clear { float: left; position: relative; top: 0; cursor: pointer; width: 66px; height: 36px; background: white; border-radius: 3px; box-shadow: 0px 4px rgba(0, 0, 0, 0.2); margin: 0 7px 11px 0; color: #888; line-height: 36px; text-align: center; /* prevent selection of text inside keys */ user-select: none; /* Smoothing out hover and active states using css3 transitions */ transition: all 0.2s ease; } /* Remove right margins from operator keys */ /* style different type of keys (operators/evaluate/clear) differently */ .keys span.operator { background: #FFF0F5; margin-right: 0; } .keys span.eval { background: #f1ff92; box-shadow: 0px 4px #9da853; color: #888e5f; } .top span.clear { background: #ff9fa8; box-shadow: 0px 4px #ff7c87; color: white; } /* Some hover effects */ .keys span:hover { background: #9c89f6; box-shadow: 0px 4px #6b54d3; color: white; } .keys span.eval:hover { background: #abb850; box-shadow: 0px 4px #717a33; color: #ffffff; } .top span.clear:hover { background: #f68991; box-shadow: 0px 4px #d3545d; color: white; } /* Simulating "pressed" effect on active state of the keys by removing the box-shadow and moving the keys down a bit */ .keys span:active { box-shadow: 0px 0px #6b54d3; top: 4px; } .keys span.eval:active { box-shadow: 0px 0px #717a33; top: 4px; } .top span.clear:active { top: 4px; box-shadow: 0px 0px #d3545d; }
 <DOCTYPE html> <html> <head> </head> <body> <div id="calculator"> <!-- Screen and clear key --> <div class="top"> <span class="clear">C</span> <div id="screen"></div> </div> <div class="keys"> <!-- operators and other keys --> <span value="7">7</span> <span value="8">8</span> <span value="9">9</span> <span class="operator" value="+">+</span> <span value="4">4</span> <span value="5">5</span> <span value="6">6</span> <span class="operator" value="-">-</span> <span value="1">1</span> <span value="2">2</span> <span value="3">3</span> <span class="operator" value="/">/</span> <span value="0">0</span> <span>.</span> <span class="eval" value="=">=</span> <span class="operator" value="*">*</span> </div> </div> </body>

PS: it should be noted that this piece of code works with several operands, but will NOT take operations precedance into account. PS:应该注意,这段代码适用于多个操作数,但不会考虑操作优先级。

Can work if you change:如果你改变可以工作:

screen.innerHTML = opers[srnVal[i]](iteration);

by经过

screen.innerHTML = eval(srnVal);

When asking JavaScript questions, it is a good idea to use one of the online JavaScript develop/test tools to create the scenario that you are having a problem with.在询问 JavaScript 问题时,最好使用在线 JavaScript 开发/测试工具之一来创建您遇到问题的场景。 This makes it much easier for others to debug your code.这使其他人更容易调试您的代码。 I typically use JSFiddle, but there are others (eg, CodePen and Plnkr).我通常使用 JSFiddle,但也有其他的(例如 CodePen 和 Plnkr)。 Here is a JSFiddle of your original code: https://jsfiddle.net/xpodpd1z/ .这是您原始代码的 JSFiddle: https ://jsfiddle.net/xpodpd1z/。

Regarding your issue, there are several logical errors in your code.关于您的问题,您的代码中有几个逻辑错误。 In particular, the iteration function and the code that handles the = operation.特别是iteration函数和处理=操作的代码。

First off, the = operation code:首先, =操作代码:

if (btnVal == '=') {
    for (var i = 0; i < srnVal.length; i++) {
        if (detectOp(srnVal[i])) {
            screen.innerHTML = opers[srnVal[i]](iteration);
        }
    }
}

You are iterating through the characters in your input ( srnVal ).您正在遍历输入中的字符( srnVal )。 When you find an operator character, you are acting on it and assigning the result to the output ( screen.innerHTML ).当您找到一个操作符字符时,您将对其进行操作并将结果分配给输出( screen.innerHTML )。 This approach may or may not be adequate when there are multiple operators in the input, depending on how you want to handle operator precedence.当输入中有多个运算符时,此方法可能合适也可能不合适,具体取决于您希望如何处理运算符优先级。 Regardless, it will not do anything right now because of the way iteration is used.无论如何,由于使用iteration的方式,它现在不会做任何事情。

Your opers variable is a hash of functions that expect an array of two numbers as input.您的opers变量是函数的散列,需要两个数字的数组作为输入。 You are referencing and calling the opers function correctly, but you are passing in a reference to a function and not an array of two numbers.您正在正确地引用和调用opers函数,但是您传递的是对函数的引用,而不是两个数字的数组。

I think your intent here was for the iteration function to return the two numbers, but you are not actually calling the function (the () to call the function is missing), and this may not work if there are multiple operators in the input.我认为您的意图是让iteration函数返回两个数字,但您实际上并没有调用该函数(缺少()来调用该函数),如果输入中有多个运算符,这可能不起作用。

If you ignore the multiple-operators scenario for now and just concentrate on number-operator-number, your logic needs to do the following:如果您暂时忽略多运营商场景而只关注数字运营商编号,您的逻辑需要执行以下操作:

  • Parse out the first number and convert it from a string to a number解析出第一个数字并将其从字符串转换为数字
  • Parse out the operator and get the function for it解析出运算符并获取它的函数
  • Parse out the second number and convert it from a string to a number解析第二个数字并将其从字符串转换为数字
  • Execute the operator on the two numbers and assign the result to the output对两个数字执行运算符并将结果分配给输出

Now for the iteration function.现在为iteration函数。 I think that it was intended to parse the numbers from the input, but it is really difficult to be sure because of the logical issues in it.我认为它旨在解析输入中的数字,但由于其中的逻辑问题,很难确定。

The first piece of code in that function looks like this:该函数中的第一段代码如下所示:

num = num + '';
for (var i = num.indexOf - 1; i > srnVal.length; i--) {
    num = srnVal[i] + num;
    return num;
}   

You are converting num to a string, then entering a loop.您正在将num转换为字符串,然后进入循环。 There are several issues in the loop code.循环代码中有几个问题。 First off, num.indexOf is a function and you are not calling it (the () are missing again).首先, num.indexOf是一个函数,您没有调用它( ()再次丢失)。 Second, your loop condition is i > srnVal.length and then on the next line you are accessing srnVal[i] .其次,您的循环条件是i > srnVal.length ,然后在下一行您正在访问srnVal[i] This will cause an out-of-bounds error.这将导致越界错误。

I'm reluctant to just fix it for you since appear to be learning JavaScript.由于似乎正在学习 JavaScript,因此我不愿意为您修复它。 I think you need to start by doing some rubber duck debugging on your iteration function to decide exactly what it is you intend it to do.我认为您需要首先对iteration函数进行一些橡皮鸭调试,以准确确定您打算做什么。

I think the problem is in the first for loop where you forgot to add parentheses.我认为问题在于您忘记添加括号的第一个 for 循环。

span[i].onclick = theCode; should be span[i].onclick = theCode();应该是span[i].onclick = theCode();

You are probably getting strings instead of numbers when you run the calculation.运行计算时,您可能得到的是字符串而不是数字。 Use parseInt() to type juggle.使用parseInt()输入杂耍。 I would also recommend use console.log() to figure out exactly what is getting passed into the calculation function.我还建议使用console.log()来准确确定传递给计算函数的内容。 Once you know that, I imagine that solve this problem will be relatively easy.一旦你知道了,我想解决这个问题会相对容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM