【问题标题】:JavaScript calculator displays NaNJavaScript 计算器显示 NaN
【发布时间】:2016-02-19 15:40:54
【问题描述】:

尝试制作一个简单的 javascript 计算器并遇到问题,当按下按钮并激活功能控制台时反映 NaN。无法弄清楚什么是问题。功能以某种方式工作是不正确的。代码在 sn-p 中。

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>

【问题讨论】:

  • 呃,代码在哪里?如果您不提供代码,我们将无法帮助您。
  • 请提供您的代码?
  • 设置断点或在脚本中使用debugger 命令,这样您就可以单步执行每一行,并查看每一步的所有变量值。将是宝贵的学习经验
  • 以前做过,不明白为什么代码没有执行。我认为问题在于,代码读取的是操作数,而不是数组中的数字。所以我想有人可以帮我解决这个问题。

标签: javascript html calculator


【解决方案1】:

没有更多细节很难回答 - 但 NaN(不是数字)可能暗示您的计算器正在尝试对非数字执行数字运算。

要解决,可以将数字变量包装在 parseFloat() 中,即

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

变成

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

编辑:

根据您提供的代码,我认为将我的修复应用到您所做的一些 innerHTML 拉动应该可行。

【讨论】:

    【解决方案2】:

    如果你改变可以工作:

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

    通过

    screen.innerHTML = eval(srnVal);
    

    【讨论】:

    • 应该让它不用评估
    【解决方案3】:

    在询问 JavaScript 问题时,最好使用在线 JavaScript 开发/测试工具之一来创建您遇到问题的场景。这使其他人更容易调试您的代码。我通常使用 JSFiddle,但也有其他的(例如 CodePen 和 Plnkr)。这是您原始代码的 JSFiddle:https://jsfiddle.net/xpodpd1z/

    关于您的问题,您的代码中有几个逻辑错误。特别是iteration 函数和处理= 操作的代码。

    首先,= 操作码:

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

    您正在遍历输入中的字符 (srnVal)。当您找到一个操作符字符时,您正在对其进行操作并将结果分配给输出 (screen.innerHTML)。当输入中有多个运算符时,此方法可能合适,也可能不合适,具体取决于您希望如何处理运算符优先级。无论如何,由于iteration 的使用方式,它现在不会做任何事情。

    您的opers 变量是函数的散列,需要两个数字的数组作为输入。您正确地引用和调用了opers 函数,但您传入的是对函数的引用,而不是两个数字的数组。

    我认为您的意图是让 iteration 函数返回两个数字,但您实际上并没有调用该函数(缺少调用该函数的 ()),如果有,这可能不起作用输入中有多个运算符。

    如果您暂时忽略多运算符场景而只关注数字-运算符-编号,您的逻辑需要执行以下操作:

    • 解析出第一个数字并将其从字符串转换为数字
    • 解析出运算符并获取它的函数
    • 解析出第二个数字并将其从字符串转换为数字
    • 对两个数字执行运算符并将结果分配给输出

    现在是iteration 函数。我认为它的目的是从输入中解析数字,但由于其中的逻辑问题,确实很难确定。

    该函数中的第一段代码如下所示:

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

    您正在将num 转换为字符串,然后进入循环。循环代码中有几个问题。首先,num.indexOf 是一个函数,您没有调用它(() 再次丢失)。其次,您的循环条件是i &gt; srnVal.length,然后在下一行您正在访问srnVal[i]。这将导致越界错误。

    我不太愿意为您修复它,因为我似乎正在学习 JavaScript。我认为您需要首先在您的 iteration 函数上执行一些 rubber duck debugging 来确定您打算做什么。

    【讨论】:

    • 您认为将操作优先级考虑在内的最佳方法是什么?
    • 如果您正在编写计算器,请查看反向波兰表示法。将输入解析为该格式是处理优先级的好方法。
    【解决方案4】:

    你的问题出在这条线上

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

    您正在使用 opers[srnVal[i]] 正确获取您的操作函数,但是当它需要一个数组或 2 个数字时,您调用它同时给它一个函数作为参数。您最终尝试使用undefined 进行数值运算,得到NaN

    这是你需要修复的部分。

    编辑:我真的不确定你的 iteration 函数应该做什么,但在我看来它是一些失败的 javascript,如果它被执行会产生错误反正。您需要在这里做的是解析您的表达式并评估结果。我已经编写了一个工作示例,这是使评估工作的一段代码:

    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:应该注意,这段代码可以处理多个操作数,但不会考虑操作优先级。

    【讨论】:

    • 用 (num) var num = []; 设置函数迭代我认为它应该有帮助,但它没有。我不确定我是否知道如何以另一种方式实现它。
    • @VladyslavNaidonov 我添加了一个 sn-p 并重点关注替换失败部分的代码。请注意,虽然它是一个工作示例,但它并不完整,并且将尊重操作优先级。你必须改进它。
    【解决方案5】:

    运行计算时,您可能得到的是字符串而不是数字。使用parseInt() 输入杂耍。我还建议使用console.log() 来确定传递给计算函数的确切内容。一旦你知道了,我想解决这个问题会相对容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多