面试官:如何手写一个简易计算器?

前言

今天面试的时候也是遇到一家公司的面试官,我以为它会像往常的面试官一个,先让我做个自我介绍,结果没想到上来就给我一道面试题,让我先手写一个计算器,我感觉还蛮有意思的,就自己尝试了一下,也是实现了一些基本的计算器功能,这里我就来给大家分享一下

实现思路

要实现一个这样的简易计算器,首先咱们就要在输入框部分,显示咱们刚刚输入的数字或者符号,这里我是直接通过原生js获取输入框的dom结构,使用getElementById方法获取iddisplay的输入框元素,并通过.value将它显示在输入框上的,如果用vue写的话,也可以直接在input框里用v-model双向绑定我们输入的数据,然后就是设置四个函数appendNumber(number)、appendOperator(operator)、 clearDisplay()、calculateResult()来实现当用户分别点击数字、操作符、清空按钮、‘=’计算按钮时触发的事件,实现这四个功能就差不多了。

具体实现

首先关于页面布局,我就用了一个输入框和许多button按来呈现

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>简易计算器</title>
  </head>
  <body>
    <div class="calculator">
      <input type="text" id="display" />
      <div class="buttons">
        <!-- 按钮 -->
      </div>
    </div>
  </body>
</html>

然后关于按钮的样式,就是其实计算器里的按钮排放的都很整齐,一行一列的排放,所以首先想到的就是弹性布局,这里我用的是网格布局,原理和弹性布局差不多,

body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
  }
.buttons {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 5px;
  } 

这里将body设置为弹性容器是为了让这个计算器在浏览器的正中间呈现,然后再将buttons父容器设置成网格布局,通过grid-template-columns: repeat(4, 1fr)定义一个网格布局中的列布局。将容器划分为四列,并且每一列的宽度为可用空间的等分之一。这样里面的每一个按钮就可以有序排放了。

最后就是js中这四个函数的实现了

appendNumber(number)

function appendNumber(number) {
      const display = document.getElementById('display');
      //console.log(display);
      display.value += number;
      //console.log(display.value);
    }

appendNumber(number): 向显示屏追加数字。当用户点击数字按钮时,该按钮的onclick事件触发appendNumber(7)函数。该函数接收一个参数number,表示用户点击的数字。函数内部获取到<input>元素,并将其当前值与数字7相加。最后更新<input>元素的值。

  1. 获取输入框:
    • const display = document.getElementById('display');: 使用getElementById方法获取iddisplay的输入框元素。
  2. 追加数字:
    • display.value += number;: 将用户点击的数字追加到输入框当前的值后面。这里的+=操作符将新的数字附加到display.value的末尾。

appendOperator(operator)

function appendOperator(operator) {
      const display = document.getElementById('display');
      // 防止连续输入运算符
      if (display.value.endsWith('+') || display.value.endsWith('-') ||
          display.value.endsWith('*') || display.value.endsWith('/')) {
        return;
      }
      // 不允许在没有任何数字的情况下输入负号
      if(operator === '-' && display.value === '') {
        return;
      }
      display.value += operator;
    }

这个函数用于向计算器显示屏追加运算符。

  1. 获取显示屏元素:

    const display = document.getElementById('display');: 使用getElementById方法获取iddisplay<input>元素。

  2. 防止连续输入运算符:

if (display.value.endsWith('+') || display.value.endsWith('-') ||   display.value.endsWith('*') || display.value.endsWith('/')) { return; }

这段代码检查显示屏当前的值是否以任何一个运算符(+-*/)结尾。

如果是,则阻止进一步的操作,即不追加新的运算符。

3.不允许在没有任何数字的情况下输入负号:

if (operator === '-' && display.value === '') { return; }

这段代码检查如果用户输入的是负号-,并且显示屏当前为空(即display.value的值为'')。

如果满足这两个条件,则阻止负号的追加。

4.追加运算符:

display.value += operator;: 如果上述条件都不满足,则将用户点击的运算符追加到显示屏的当前值后面。

clearDisplay()

function clearDisplay() {
      const display = document.getElementById('display');
      display.value = '';
    }

这个函数用于清空计算器显示屏上的内容

1.获取显示屏元素:

const display = document.getElementById('display');: 使用getElementById方法获取iddisplay<input>元素。

2.清空显示屏内容:

display.value = '';: 将<input>元素的值设置为空字符串'',从而清空显示屏上的内容。

calculateResult()

function calculateResult() {
      const display = document.getElementById('display');
      try {
        // 使用Function构造函数避免eval的安全问题
        const result = new Function(`return ${display.value}`)();
        display.value = result;
      } catch(error) {
        alert("无效的表达式");
        display.value = '';
      }
    }

这个函数用于计算计算器显示屏上的数学表达式的结果,并将结果显示在显示屏上

1.获取显示屏元素:

const display = document.getElementById('display');: 使用getElementById方法获取iddisplay<input>元素。

2.计算结果:

try { ... }: 使用try块来捕获可能发生的错误。

const result = new Function(return ${display.value})();

这里咱们用Function构造函数来安全地计算显示屏上的数学表达式。

new Function(return display.value‘)‘:创建一个新的匿名函数,该函数的主体是return{display.value}其中${display.value}会被替换成显示屏上的实际值。

(): 立即执行这个新创建的函数,得到计算结果,并将其存储在result变量中。

display.value = result;: 将计算结果赋值给<input>元素的值,从而更新显示屏。

3.处理错误:

catch (error) { ... }: 如果在计算过程中发生错误(例如无效的表达式),则捕获这个错误。

alert("无效的表达式");: 显示一个警告对话框,告知用户输入的表达式无效。

display.value = '';: 清空显示屏的内容。

其实在上面计算函数结果这个地方我使用Function构造函数来安全地计算一个字符串形式的数学表达式的方法之一,new Function 是一个特殊的构造函数,它接受一个或多个字符串参数,并返回一个新的函数对象。字符串参数构成了新函数的源代码。当然也可以用内置函数eval来计算最后的结果,它的功能也很强大,但是它有个缺点就是不太安全,所以我使用Function构造函数来执行字符串形式的代码比使用eval更安全,因为Function构造函数在执行时会创建一个新的作用域,不会污染全局作用域。

好啦,今天的分享就到这里啦。最后给大家附上完整的代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>简易计算器</title>
  </head>
  <body>
    <div class="calculator">
      <input type="text" id="display" />
      <div class="buttons">
        <button onclick="clearDisplay()">C</button>
        <button onclick="appendNumber('7')">7</button>
        <button onclick="appendNumber('8')">8</button>
        <button onclick="appendNumber('9')">9</button>
        <button onclick="appendOperator('+')">+</button>
        <button onclick="appendNumber('4')">4</button>
        <button onclick="appendNumber('5')">5</button>
        <button onclick="appendNumber('6')">6</button>
        <button onclick="appendOperator('-')">-</button>
        <button onclick="appendNumber('1')">1</button>
        <button onclick="appendNumber('2')">2</button>
        <button onclick="appendNumber('3')">3</button>
        <button onclick="appendOperator('*')">*</button>
        <button onclick="appendNumber('0')">0</button>
        <button onclick="appendOperator('.')">.</button>
        <button onclick="calculateResult()">=</button>
        <button onclick="appendOperator('/')">/</button>
      </div>
    </div>
  </body>
</html>
<script>
    function appendNumber(number) {
      const display = document.getElementById('display');
      //console.log(display);
      display.value += number;
      //console.log(display.value);
    }
    function appendOperator(operator) {
      const display = document.getElementById('display');
      // 防止连续输入运算符
      if (display.value.endsWith('+') || display.value.endsWith('-') ||
          display.value.endsWith('*') || display.value.endsWith('/')) {
        return;
      }
      // 不允许在没有任何数字的情况下输入负号
      if(operator === '-' && display.value === '') {
        return;
      }
      display.value += operator;
    }
    function clearDisplay() {
      const display = document.getElementById('display');
      display.value = '';
    }
    function calculateResult() {
      const display = document.getElementById('display');
      try {
        // 使用Function构造函数避免eval的安全问题
        const result = new Function(`return ${display.value}`)();
        display.value = result;
      } catch(error) {
        alert("无效的表达式");
        display.value = '';
      }
    }
</script>
<style>
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
  }
  .calculator {
    border: 1px solid #ccc;
    padding: 20px;
    background-color: white;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  }
  input {
    width: 100%;
    height: 40px;
    margin-bottom: 10px;
    text-align: right;
    font-size: 18px;
  }
  .buttons {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 5px;
  }
  button {
    height: 40px;
    font-size: 18px;
    cursor: pointer;
  }
</style>

需要更多面经的同学转发本文+关注+【点击此处】即可获取! 加油

整份文档一共有几百道题万字以上,全都是近期高频面试题,不仅有答案,而且有详细的解析,为了不影响大家的阅读体验就只展示了部分内容,还望大家海涵,这份文档绝对可以帮助大家提升复习效率,加大面试的成功率,也节省大家在网上搜索资料的时间来学习,最后祝所有复习过我文章里学习内容的小伙伴们,每个人都能拿到心仪offer,欢迎大家讨论交流!

  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值