ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] Toy Project - 계산기 만들기 ( Calculator )
    Front End/JAVASCRIPT 2022. 3. 2. 06:56

    안녕하세요 여러분 

    야매 코린이 까불린입니당 ~ 

    오늘 하루도 잘 보내셨나요? 

     

     

     

     

    전 요즘 호텔 포트폴리오 도안을 기획해보는 중이에요.

    이번엔 전에 사용했던 코드들 보다 훨씬 더 '클린?' 하고 재사용성면에서

    보다 발전된 포트폴리오를 제작해보고자

    다시 한번 HTML Tag 들과 CSS, Sass 개념을 바로 잡고 있는 중인데요~

    정말 머리를 쥐어짜내야하는 고통인 것 같아요.. 

     

    하지만 전 이렇게 효율성을 중요시하고 고민하고 고민하는 기획이 너무 즐겁답니다 !

    이걸 코드로 풀어내서 결과물을 볼때의 그 희열은 말해 모해..♥️ 

    여러분도 같은 마음이셔서 이렇게 코딩공부 하시는거겠죠? 

     

    하지만, 역시 코린이는 하루이틀 자바스크립트 공부 안하게되면 

    뭔가 조금 개념을 알 것도 같더라고 다시 잊는 것 같아요.

    할 때 꾸준히 공부해야 비로소 제것이 되겠죠 ! 

    더 열심히 해야겠어요 ! 

     

    제가 너무 안일했던 것 같아서,

    자바스크립트의 흔하디 흔한 프로젝트 중 하나인

    계산기를 만들어 보도록 하겠습니다.

     

    제가 이 계산기를 만들기 위해 참고한 영상은 유투브 제로초님의 자바스크립트 강의 입니다. 

     

    이 글은 영상의 2차 배포용이 아니며,

    개인적으로 영상을 보고 공부하며, 보고느낀 점 그리고 강의하신 내용을 토대로

    제가 다시 보고 공부하기 위해 작성된 글임을 알립니다!

    자 그럼 시작해 보겠습니다.


    1. 순서도 만들기 💬

    영상에서 말씀하셨던 것처럼,

    저는 항상 순서도/Planning을 항상 하고 일을 시작하는 편입니다 ! 

    다만, 개발자다운 순서도는 제가 순서도보다 스텝이 많았답니다.

    예를들어, '1+1 이 = 이 눌렸을 때 계산을 한다'  에서 '값을 출력한다.' 까지 생각을 해야하는 부분이니,

    개발자의 입장에서 컴퓨터에게 하나하나 명령을 해야 한다는 걸 다시금 깨달았습니다. 

    민망하지만, 제로초 님께서 설명해주신대로 순서도를 그려봤습니다. 

    하지만, 동영상을 보고 한 번 그려본 것으로는 제가 정확히 이해를 했다는 걸 

    증명할 수 없어서, 영상을 멈추고, 제 생각의 흐름대로 한 번 더 그려서 

    컴퓨터의 입장에서 생각하며 순서도를 그려보려 노력했습니다. 

     


    2. HTML / CSS 작성 👩‍💻

    아래와 같은 코드는 제로초님의 깃헙에서도 제공이 됩니다만,

    이렇게 제공 된 것만 사용하시면 연습해 볼 시간이 없을 것 같아

    혼자서도 마크업 작성하려고 연습을 해보시는 걸 추천합니다 ! 

    한 두번 해보니까 스르르르륵 써지네요 ! 

     

     

    input 태그의 readonly 라는 건 작성은 불가능 하고 읽기만 가능하게 만드는 것이라고 합니다.

    대신 자바스크립트로는 작성이 가능하지만, 사용자가 index에서 작성은 불가능하게 한다고 합니다 ! 

    <!DOCTYPE html>
    <head>
      <meta charset="utf-8">
      <title>계산기</title>
      <style>
        * { box-sizing: border-box; }
        #result { width: 180px; height: 50px; margin: 5px; text-align: right; }
        #operator { width: 50px; height: 50px; margin: 5px; text-align: center; }
        button { width: 50px; height: 50px; margin: 5px; }
      </style>
    </head>
    
    <body>
      <input readonly id="operator">
      <input readonly type="number" id="result">
      <div class="row">
        <button id="num-7">7</button>
        <button id="num-8">8</button>
        <button id="num-9">9</button>
        <button id="plus">+</button>
      </div>
      <div class="row">
        <button id="num-4">4</button>
        <button id="num-5">5</button>
        <button id="num-6">6</button>
        <button id="minus">-</button>
      </div>
      <div class="row">
        <button id="num-1">1</button>
        <button id="num-2">2</button>
        <button id="num-3">3</button>
        <button id="divide">/</button>
      </div>
      <div class="row">
        <button id="clear">C</button>
        <button id="num-0">0</button>
        <button id="calculate">=</button>
        <button id="multiply">x</button>
      </div>
    </body>

     

     

     

    이게 완성이 되면 

    아래와 같은 

    계산기가 완성이 됩니다 ♥️

    그럼 이제 자바스크립트를 작성할 준비가 완료된 겁니다 ! 


    3. JavaScript 숫자부분 작성하기 VER. 1 

    let numOne = '';
        let numTwo = '';
        let opertor = '';
        const $operator = document.querySelector('#operator');
        const $result = document.querySelector('#result');

    우선 변수와 상수선언을 해줍니다.

    그리고 클릭이벤트를 선언할 숫자들에게 하나씩 함수를 적어줍니다... 

        document.querySelector('#num-0').addEventListener('click', () => {
          if (operator) {
            numTwo += '0';
          } else {
            numOne += '0';
          }
          $result += '0';
        });
        document.querySelector('#num-1').addEventListener('click', () => {
          if (operator) {
            numTwo += '1';
          } else {
            numOne += '1';
          }
          $result += '1';
        });
        document.querySelector('#num-2').addEventListener('click', () => {
          if (operator) {
            numTwo += '2';
          } else {
            numOne += '2';
          }
          $result += '2';
        });

    이쯤 되면, 뭔가 잘 못됐다고 생각했습니다.

    코드의 중복이 상당하지만, 전 이를 해결할 수 있는 지식이 없어서 방법을 모르지만,

    영상을 멈추고 우선 생각을 해보았습니다. 

     

    그래서 내린 결론은 : 

    1. 반복되는 코드를 매개변수 안에서 함수에 선언하거나,

    2. 변수 i 를 숫자와 연관짓는 무언가?를 만들어, 함수와 연결시킨다 ... 

    말이 안되는 것 같아보이지만, 우선 제가 생각한 것을 글로 옮기니,

    두가지 다 비슷해 보이긴 하네요. 

     

     

    우선, 함수안의 중복을 해결하는 정답은 매개변수를 만드는 것이었습니다 ! 

    대부분 비슷한데 애매하게 다른 저 숫자 1, 2, 3 의 부분을 number라는

    매개변수로 지정해서 바꾸면 중복을 줄일 수 있게됩니다 ! 

     

    그래서 바꿔보면 아래와 같은 결과가 나옵니다.

        document.querySelector('#num-0').addEventListener('click', (number) => {
          if (operator) {
            numTwo += number;
          } else {
            numOne += number;
          }
          $result += number;
        });

     

     

     

     

    이렇게 중복코드를 없앤 후, if문을 변수선언해주고, 인수에 해당 숫자를 넣어주면 됩니다 ! 

    const onClickNumber = (number) => {
          if (operator) {
            numTwo += number;
          } else {
            numOne += number;
          }
          $result += number;
        };
    
        document.querySelector('#num-0').addEventListener('click', onClickNumber('0'));
        document.querySelector('#num-1').addEventListener('click', onClickNumber('1'));
        document.querySelector('#num-2').addEventListener('click', onClickNumber('2'));

     

     

     

    다만 여기서 문제가 생깁니다.

    addEventListener( 1, 2 )

    1 은 이벤트 / 어떠한 액션,

    그리고 2 는 함수 자리인데

    지금과 같은 경우엔 매개변수 안의 함수에 리턴 값이

    정해져 있지 않기때문에 2번의 자리는 undefined 가 되어버리게 됩니다.

     

     

     

     

    그래서 아래와 같이 리턴을 먼저 선언해주고,

    리턴 값 안에 함수를 선언해주면 됩니다. 

     

    여기서 한가지 더 생략가능한 것!!!! 

    화살표 함수 중괄호와 return 이 있다면 생략이 가능합니다 ( 오호! )

    그래서 (number) => () => 연달아 나오는 고차 함수가됩니다.

     

    고차함수 ( high order function ) : 

    - 함수안에 함수가 있다 / 함수가 함수를 리턴하고 있다.

     

    고차함수를 사용하나?!

    - 함수간의 중복을 최소화 하기위해

     

        const onClickNumber = (number) => (event) => {
            if (operator) {
            numTwo += number;
          } else {
            numOne += number;
          }
          $result += number;
          };
        };

     

    그런데 뜬금없는 저 event 는 무엇이냐 ! 

    하신다면, 

    이 예시를 봐주세요. 

    const a = (event) => {console.log(event.target.value)};
    
    document.querySelector('#num-0').addEventListener('click', a);
    //a(event);

    이 상황에서 

    클릭 이라는 이벤트가 생기면, a 라는 함수가 실행이 되는데 누가 실행을 하는걸까요?  

    - 주석에 있는 것 처럼 브라우저가 몰래 실행을 해줍니다. 다만 ! 실행을 하면서 event 라는 객체를

    만들어 인수로 넣어주고, 그 이벤트가 주석에 있는 것 처럼 매개변수로 전달이 되는 겁니다 ! 

     

     

     

     


    4. JavaScript 숫자부분 작성하기 VER. 2

    3번에서 했던 것은 중복코드를 줄이기 위한 고차함수개념을 설명하기 위해 짚어본 내용이었는데요~ 

    고차함수를 쓰지 않고도 제거를 할 수 있답니다 ! 

    버튼에 이벤트를 생성해놨기 때문에 클릭 이벤트가 생겼을때 textContent가 보여질 수 있겠죠 ! 

    3번과는 다르게 굉장히 간단한,, 방법입니다 ! 

    하지만 고차함수도 상황에 따라 사용할 때가 많다고하니 꼭 공부해놓으시기 바랍니다 ! 

    const onClickNumber = (event) => {
            if (operator) {
            numTwo += event.target.textContent;
          } else {
            numOne += event.target.textContent;
          }
          $result.value += event.target.textContent;
          };
        };
    
        document.querySelector('#num-0').addEventListener('click', onClickNumber);
        document.querySelector('#num-1').addEventListener('click', onClickNumber);
        document.querySelector('#num-2').addEventListener('click', onClickNumber);

     


    5. JavaScript 연산자 작성하기

    연산자는 고차함수를 사용해서 작성되었습니다 ! 

    ㅠㅠ저도 써놓고 이게 무슨소린가 싶어서, 

    다시 천천히 생략된 부분 다시 추가해서 공부해봐야 할 것 같아요.. (엉엉ㅠㅠ)

    const onClickOperator = (op) => () => {
            if (numOne) {
              operator = op;
              $operator.value = op;
            } else {
              alert ('숫자를 입력하세요.');
            }
        }
    
        
        document.querySelector('#plus').addEventListener('click', onClickOperator('+'));
        document.querySelector('#minus').addEventListener('click', onClickOperator('-'));
        document.querySelector('#divide').addEventListener('click', onClickOperator('/'));
        document.querySelector('#multiply').addEventListener('click', onClickOperator('*'));

     

     


    6. JavaScript 두번째 숫자 작성시 첫번째 숫자 없어지기

    numTwo가 비어있는 경우에는 어떠한 숫자가 입력됐을때, 그 입력값을 '' 로 지워줘라 !

    라는 코드를 추가해 줬습니다. 

    const onClickNumber = (event) => {
          if (operator) {
            
            if (!numTwo) {
              $result.value = '';
            }
            numTwo += event.target.textContent;
          } else {
            numOne += event.target.textContent;
          }
          $result.value += event.target.textContent;
        };

     

    하나를 덧붙이자면, if 중첩문이 위와같이 섞이거나 많아지게 된다면 이해하기 힘들어질 수 있기때문에,

    if 중첩문 간소화하는 방법을 따라 아래처럼 코드를 한단계 간단하게 만들어 보았습니다. 

    방법은 : 

    1. 공통된 절차를 각 분기점에 넣는다.

    2. 분기점에서 제일 짧은 절차를 제일 앞부분으로 넣고 변수에 ! 를 붙여 반대로 바꿔준다.

    3. 짧은 절차 후, return 함수 (if문) 이나 break (for문)을 넣어 종료한다. if 문의 경우 return 으로 종료될 경우

    후에 나오는 else 가 필요없게되어 새로운 if문이 생겨서 if 안의 else, else if 를 줄이는 것으로 단계가 간단해진다 ! 

    const onClickNumber = (event) => {
          if (!operator) {
            //비어있다 
            numOne += event.target.textContent;
            $result.value += event.target.textContent;
            return; //함수종료 시켜버리기
          }
    
          // 비어있지 않다. 
          if (!numTwo) {
            $result.value = '';
          }
          numTwo += event.target.textContent;
          $result.value += event.target.textContent;
        };

     

     

     

     

     


    7. JavaScript 결과 계산하기 

    #calculate 이벤트리스터에 화살표 함수추가 후, 그안에 아래 함수를 추가해주었는데요! 

    여기서 더하기에만 parseInt를 붙인이유는 

    자바스크립트에서는 숫자를 더하게 되면 문자열끼리 더하게 되는거라 

    반드시 숫자라는걸 명시하고 더하게끔 해줘야 하기 때문입니다.

    빼기, 곱하기, 나누기는 바로 숫자로 명시되어지지만, 더하기는 다르기때문에

    parseInt가 추가된 것입니다. 하지만 parseInt 를 다 적어주셔도 무관합니다. 

    document.querySelector('#calculate').addEventListener('click', () => {
          if (numTwo) {
          switch (operator) {
            case '+':
              $result.value = parseInt(numOne) + parseInt(numTwo);
              break;
            case '-':
              $result.value = numOne - numTwo;
              break;
            case '*':
              $result.value = numOne * numTwo;
              break;
            case '/':
              $result.value = numOne / numTwo;
              break;
            default:
              break;
          }
        } else {
          alert('숫자를 먼저 입력하세요.');
        }
      });

     

     


    8. JavaScript Clear 버튼 -> 클리어 되기 

    아래와 같이 초기화를 하시면 됩니다 !

       document.querySelector('#clear').addEventListener('click', () => {
          numOne = '';
          operator = '';
          numTwo = '';
          $operator.value = '';
          $result.value = '';
        });

     

     

     

    오늘도 이렇게 많은 지식을 얻어서 글을 마치겠습니다.

    전 제글을 다시 보며 공부를 해야할것 같습니다.. 

    특히 고차함수 부분은 한번에 알아보는게 아직은 어려운것 같고,

    if문 중첩도 연습을 해봐야할 부분 인것 같습니다 ! 

     

     

     

    여러분,

    오늘도 즐 코 딩 입니다 ! 

    많은 지식들을 효율적으로 얻는 하루가 되시길 바랄게요 ! 

    그럼 전 이만 ♥️

     

     

     

     

    'Front End > JAVASCRIPT' 카테고리의 다른 글

    [JavaScript] 비디오 풀스크린 기능 구현  (0) 2022.02.25
Designed by Tistory.