계산하기 (함수 학습)
➕ readonly 속성
: input창에 키보드로 입력할 수 없고, 읽기만 가능하도록 설정(자바스크립트를 이용한 입력은 가능)
➕ 단축키★
Alt + Shift + ⇅ : 코드 복사/붙여넣기
자바스크립트에서 태그를 변수에 저장할 때, 태그명 앞에 $
를 붙여 변수이름을 '$태그명' 이라 설정(강사님만의 규칙)
중복된 코드를 작성하고 있다면 잘못 작성하고 있는 것!
중복을 제거해 코드를 줄이도록 다시 생각해봐야 한다!
✨ Tip! 함수에서 중복을 제거하려면 중복되는 코드 안에서 '달라지는 특정 부분'을 매개변수로 만든다.
매개변수로 만들어줌으로써 중복(함수)인 전체 코드를 변수에 저장해준다. (함수가 필요할 때마다 변수를 사용!)
※ 자바스크립트 변수에만 데이터를 바꾸는 것이 아니라 동시에 💻화면에 표시되는 데이터도 바꿔줘야 한다!
(맨 마지막 3번째 흐름 코드 참고)
// 1️⃣번째 흐름
const onClickNumber = (number) => {
if (operator) { // 연산자 변수 들어있는 경우
numTwo += number;
} else { // 연산자 변수 비어있는 경우
numOne += number;
}
$result.value += number; // 화면에 값 표시
// return undefined;
};
document.querySelector('#num-0').addEventListener('click', onClickNumber('0'));
📌 코드 흐름 파악하기!
addEventListener 메서드의 두번째 인자인 '함수 자리'에 함수가 아닌 undefined를 return하지 않도록, (버튼을 click해도 아무것도 실행되지 않는다!😱)
return 함수 안에 실제로 동작하는 코드를 넣음으로써 함수가 실행되고 함수 실행값이 return 되도록 한다. (즉, 고차함수를 사용한다.)
// 2️⃣번째 흐름
// 함수 실행된 값을 리턴하기 위해 return 안에 함수를 넣음
const onClickNumber = (number) => {
/* 🔽 return 안으로 이동!!
if (operator) {
numTwo += number;
} else {
numOne += number;
}
$result.value += number;
*/
return = () => {
if (operator) {
numTwo += number;
} else {
numOne += number;
}
$result.value += number;
};
};
// 3️⃣번째 흐름
// 화살표 함수는 중괄호와 return 예약어 생략 가능
// '(number) => () =>'와 같이 화살표가 연달아 나오는 형태를 취함
// ↳'함수 안에 함수가 있다', '함수가 함수를 리턴한다'로 해석 (∴고차함수)
// ↳매개변수에 number를 넣고 함수 실행 => return 함수를 실행해 앞의 함수 실행값을 리턴
const onClickNumber = (number) => () => {
if(operator) {
numTwo += number;
} else {
numOne += number;
}
$result.value += number;
};
원래 빈 괄호 모양이었던 자리에는 브라우저가 제공하는 event 매개변수가 존재한다.
아래의 코드처럼 고차함수 형태로 작성함으로써 addEventListenter 함수에 들어가고 중복도 제거할 수 있다.
// 중괄호({)와 return을 생략한 형태의 고차함수
const onClickNumber = (number) => (event) => {
...
};
🎊event 객체 간단 예시
click 이벤트가 발생하면 eventClick 함수가 실행되는데, 사실 브라우저가 eventClick 함수를 몰래 호출한다.
브라우저가 event 객체를 만들어 그 객체는 인수로 넣어지고 함수의 매개변수로 전달되어 함수가 실행된다.
const eventClick = (event) => {
console.log(event.target.value);
};
document.querySelector('.#input').addEventListener('click', eventClick);
// eventClick(event);
함수를 만들어내는 함수이며, 함수 간의 중복을 제거할 수 있다.
(실무에서도 중괄호, return 생략된 코드를 많이 사용)
<매개변수가 없는 고차함수>
// 아래 코드와 동일함
const func = () => {
return () => {
console.log('hello');
};
};
// 함수의 리턴값을 변수에 넣어주는 형태
// 함수를 호출하는 부분이 이해가지 않는다면 return값으로 대체❗(위 코드 참고)
const innerFunc = func();
innerFunc(); // hello
<매개변수가 있는 고차함수>
고차 함수에서 중괄호({)와 return 예약어 생략 가능하다.
(화살표가 연달아 나타나는 형태 보고 당황하지 않기!🤨)
// 빈 괄호부터는 return하는 부분으로 이해
const func = (msg) => () => {
console.log(msg);
};
// 위와 같은 코드
const func = (msg) => {
return () => {
console.log(msg);
};
};
// func 함수 호출하면 console.log(매개변수)되는 함수가 반환
const innerFunc1 = func('hello');
const innerFunc2 = func('javascript');
const innerFunc3 = func();
innerFunc1; // hello
innerFunc2; // javascript
innerFunc3; // undefined: 빈 값의 경우
/* ----- 대체 코드(중괄호 return 생략) ----- */
const innerFunc1 = () => {
console.log('hello');
};
const innerFunc2 = () => {
console.log('javascript');
};
const innerFunc3 = () => {
console.log();
};
➕ 단축키 마우스 휠 클릭 + 드래그 : 원하는 부분 드래그하여 줄마다 커서 위치하도록 함. (원하는 부분 한번에 선택해 삭제 가능)
✨ 추가 Tip! (실력차를 나타내는 잔재주🤓)
(태그의 값을 나타내는 속성으로 textContent를 사용하는 일반 태그의 경우) event.target.textContent를 사용해 고차함수 사용하지 않고 중복 코드를 줄일 수 있다.
계산기에서 피연산자 두 개의 숫자가 연속으로 표시되지 않도록 만들기
=> 두번째 숫자를 클릭하기 전에, 이전에 클릭했던 첫번째 숫자를 화면에서 지워 빈 화면으로 만들기
const onClickNumber = (event) => {
if (operator) {
if (!numTwo) { // 두번째 숫자를 클릭하고 변수에 저장되기 직전에
$result.value = ''; // 빈 화면으로 표시
}
...
};
};
if문 안에 if문이 들어가는 중첩 형태는 최대한 줄여 코드를 보기 쉽게 작성하는 것이 좋다.
<중첩 if문 제거하는 방법>
if문 다음에 나오는 공통된 절차를 각 분기점 내부에 넣는다.
분기점에서 짧은 절차부터 실행하도록 if문을 작성한다.
(✳ 내가 이해하기 위한 추가 설명: 기존에 작성한 if문이 반대 형태(if-긴 절차, else-짧은 절차)인 경우, 작은 if-else를 감싸는 if 조건문에 !
를 넣어 반대로 실행되도록 만든다.)
짧은 절차가 끝나면 return(함수 내부의 경우)이나 break(for문 내부의 경우)로 중단한다.
else를 제거한다(이때 중첩 하나가 제거된다).
(✳ 내가 이해하기 위한 추가 설명: return은 코드를 종료하므로 뒤에 있는 else가 필요 없다. 없어짐으로써 중첩 if문 → 2개의 if문 형태로 바뀜)
다음 중첩된 분기점이 나오면 1~4의 과정을 반복한다.
연산자에 따라 다르게 실행되는 코드 각각 작성하기
더하기(+)는 숫자도 문자열로 판단해 parseInt를 사용해야 한다.
이와 달리 빼기(-), 곱하기( * ), 나누기(/)는 자동으로 문자열을 숫자로 (또는 숫자를 문자열로) 바꿔주기 때문에 parseInt를 사용하지 않아도 된다.
if (numTwo) {
switch (operator) {
case '+':
$result.value = parseInt(numOne) + parseInt(numTwo);
break;
case '-':
$result.value = parseInt(numOne) - parseInt(numTwo);
break;
case '*':
$result.value = parseInt(numOne) * parseInt(numTwo);
break;
case '/':
$result.value = parseInt(numOne) / parseInt(numTwo);
break;
default:
break;
}
}
📒숙제~ switch/case문 → if문으로 바꿔보기! (switch/case ⇄ if 연습!)
if (numTwo) {
if (operator === '+') {
$result.value = parseInt(numOne) + parseInt(numTwo);
} else if (operator === '-') {
$result.value = numOne - numTwo;
} else if (operator === '*') {
$result.value = numOne * numTwo;
} else if (operator === '/') {
$result.value = numOne / numTwo;
}
} else {
alert('숫자를 먼저 입력하세요');
}
// 중첩 if문 줄이기
if (!numTwo) {
alert('숫자를 먼저 입력하세요');
}
if (operator === '+') {
$result.value = parseInt(numOne) + parseInt(numTwo);
}
/* 이어서 -, *, / 조건문 */
계산작업을 reset하는 것이기 때문에 코드에서 초기상태(ex. 변수선언)를 맨 위에 몰아 작성하는 것이 좋다.
초기화하는 버튼을 클릭하여 이벤트가 발생하면 피연산자와 연산자 변수를 초기화하고, 값이 표시되는 화면을 빈 화면으로 만든다.
let numOne = '';
let operator = '';
let numTwo = '';
const $operator = document.querySelector('#operator');
const $result = document.querySelector('#result');
/* ...(실행코드 생략) */
// 🔽초기화 코드
document.querySelector('#clear').addEventListener('click', () => {
numOne = '';
operator = '';
numTwo = '';
$operator.value = ''; // 클릭한 연산자가 표시되는 화면
$result.value = ''; // 계산 결괏값이 표시되는 화면
});
➕ 단축키 Alt + ⇅ : (커서가 위치한)선택한 코드 위아래로 이동하여 줄바꾸기
연달아 계산하기 (계산하기 심화)
알고리즘이 바뀌면 먼저 '순서도'를 수정해 그려보고, 코드에 옮겨 작성하기❗ (머릿속으로만 생각하고 바로 코드 수정하는 습관❌)
고차함수를 이용해 return으로 함수를 반환한다....🤔
Hint : 1 + 2+ 3은 실제로 계산기에 1, +, 2, =, +, 4, = 순으로 버튼을 눌러야 한다. 두번째 '+'를 눌렀을 때 numOne, operator, numTwo 변수가 가지고 있어야 할 값이 무엇일까?
=> 첫번째 '='버튼을 클릭할 때 계산 결과를 numOne 변수에 저장하고, operator와 numTwo 변수를 비워 이어서 클릭하는 연산자와 숫자값을 저장한다.
if (operator) {
/* ...(연산자에 따라 실행되는 코드 생략) */
$operator.value = ''; // 연산자 아무것도 없이 빈 화면
numOne = $result.value; // 첫번째 숫자 변수에 이전 계산 결괏값 저장
operator = ''; // 연산자 변수 비워두기
numTwo = ''; // 두번째 숫자 변수 비워두기
} else {
alert('숫자부터 입력하세요');
}
📒숙제~ 첫번째 숫자에 음수인 '-'먼저 입력이 가능하도록 작성해보기!
📒숙제~ 중간마다 '='클릭하지 않고 이어서 계산하기 위해 연산자를 클릭했을 때 결과값이 나오도록 구현해보기!