하단문제 모름//항해2주차 - Node.js (7) 기본 연산자와 수학
1. 피연산자(operand)
연산자가 연산을 수행하는 대상.
예를 들어 3*2면 곱하기 수행하는 대상인 왼쪽 피연산자 3과 오른쪽 피연산자 2,
피연산자는 인수(argument)라고도 불림.
2. 피연산자를 하나만 받는 연산자는 단항(unary) 연산자로 함.
피연산자의 부호를 뒤집는 단항 마이너스 연산자 - 는 단항 연산자의 대표적인 예이다.
let x = 1;
x = -x;
alert( x ); // -1, 단항 마이너스 연산자는 부호를 뒤집는다
3. 두 개의 피연산자를 받는 연산자는 이항(binary) 연산자라고 함.
let x = 1, y = 3;
alert( y - x ); // 2, 이항 마이너스 연산자는 뺄셈을 한다
-----> 단항 연산자에서 뒤집는다는걸 이항 연산자에도 대입하는 걸로 착각해
-3 -(-1) = -2라고 잘못 생각했었음.
4. 나머지 연산자 %
나눈 후 나머지를 정수로 변환함,
alert( 5 % 2 ); // 5를 2로 나눈 후의 나머지인 1을 출력
alert( 8 % 3 ); // 8을 3으로 나눈 후의 나머지인 2를 출력
5. 거듭제곱 연산자 **
alert( 2 ** 2 ); // 4 (2 * 2)
alert( 2 ** 3 ); // 8 (2 * 2 * 2)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2)
정수가 아닌 숫자에도 동작함.
alert( 4 ** (1/2) ); // 2 (1/2 거듭제곱은 제곱근)
alert( 8 ** (1/3) ); // 2 (1/3 거듭제곱은 세제곱근)
6. 이항 연산자 '+' 와 문자열 연결
덧셈 연산자 + 는 대개 숫자를 더한 결과를 변환한다.
그런데!! 이항 연산자 + 의 피연산자로 문자열이 전달되면 덧셈 연산자는 덧셈X 문자열을 병합한다.
let s = "my" + "string";
alert(s); // mystring
** 이항연산자를 사용할 때는 피연산자 중 하나가 문자열이면 다른 하나도 문자열로 변환되니 주의하자**
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
//뭐가 피연산자고 문자열인지 no중요
//피연산자 중 어느하나가 문자열이면 다른하나도 문자열로 변환됨을 주목
alert(2 + 2 + '1' ); // '221'이 아니라 '41'이 출력됨
**이항 덧셈연산자는 문자열 연결과 변환이란걸 한다**
alert( 6 - '2' ); // 4, '2'를 숫자로 바꾼 후 연산 진행.
alert( '6' / '2' ); // 3, 두 피연산자가 숫자로 바뀐 후 연산 진행.
7. 단항 연산자 + 와 숫자형으로 변환 ------> 살짝 이해 떨어짐
// 숫자에는 아무런 영향을 미치지 않는다.
let x = 1;
alert( +x ); // 1
let y = -2;
alert( +y ); // -2
// 숫자형이 아닌 피연산자는 숫자형으로 변화.
alert( +true ); // 1
alert( +"" ); // 0
덧셈 연산자 +는 이항 연산자뿐만 아니라 단항 연산자로도 사용할 수 있다.
숫자에 단항 덧셈 연산자를 붙이면 이 연산자는 아무런 동작도 하지 않는다.
그러나 피연산자가 숫자가 아닌 경우엔 숫자형으로의 변환이 일어난다.
단항 덧셈 연산자는 짧은 문법으로도 Number(...)와 동일한 일을 할 수 있게 해준다.
개발을 하다 보면 문자열을 숫자로 변환해야 하는 경우가 자주 생긴다.
HTML 폼(form) 필드에서 값을 가져왔는데 그 값이 문자형일 때 같을 때.
실제로 폼에서 가지고 온 값은 대개 문자열 형태임.
이항 덧셈 연산자를 사용하면 아래와 같이 값이 문자열로 변해서 연결될거임.
let apples = "2";
let oranges = "3";
alert( apples + oranges ); // 23, 이항 덧셈 연산자는 문자열을 연결한다
원하는 대로 값을 더해주려면, 단항 덧셈 연산자를 사용해 피연산자를 숫자형으로 변화시키면 된다.
let apples = "2";
let oranges = "3";
// 이항 덧셈 연산자가 적용되기 전에, 두 피연산자는 숫자형으로 변화한다.
alert( +apples + +oranges ); // 5
// `Number(...)`를 사용해서 같은 동작을 하는 코드를 작성할 수 있지만, 더 길어짐.
// alert( Number(apples) + Number(oranges) ); // 5
**그런데 왜 이항 덧셈 연산자가 적용되기 전에 단항 덧셈 연산자가 먼저 적용될까?
그 이유는 하단에 연산자 우선순위 때문임**
8. 연산자 우선 순위
식에 둘 이상의 연산자가 있을 경우, 실행 순서는 연산자의 우선 순위대로 결정된다.
괄호 > 곱셈
우선순위 숫자가 클수록 먼저 실행.
순위가 같으면 왼쪽--->오른쪽으로 연산 수행.동일한 기호의 단항 연산자는 이항 연산자보다 우선순위가 더 높음.
순위연산자 이름기호
순위 |
연산자 이름
|
기호 |
17
|
단항 덧셈
|
+
|
17
|
단항 부정
|
-
|
16
|
지수
|
**
|
15
|
곱셈
|
*
|
15
|
나눗셈
|
/
|
13
|
덧셈
|
+
|
13
|
뺄셈
|
-
|
…
|
…
|
…
|
3
|
할당
|
=
|
…
|
…
|
…
|
단항 덧셈 연산자는 우선순위 17 > 이항 덧셈 연산자의 우선순위 13보다 높다.
So "+apples + +oranges" 에서 단항 덧셈 연산자가 덧셈보다 먼저 수행되는 이유임
9. 할당(assignment) 연산자
무언가를 할당할 때 쓰이는 = 도 연산자임.
let x = 2 * 2 + 1;
alert( x ); // 5
//계산 먼저 하고 결과가 x에 할당됨
9-1 값을 반환하는 할당 연산자 ----->조금 헷갈
x = value을 호출하면 value가 x에 쓰여지고, 이에 더하여 value가 반환된다.
let a = 1;
let b = 2;
let c = 3 - (a = b + 1);
alert( a ); // 3
alert( c ); // 0
위 예제에서 표현식 (a = b + 1)은 a에 값을 할당하고, 그 값인 3을 반환한다.
그리고 반환 값은 이어지는 표현식에 사용된다.
괴상한 코드라고 느껴지겠지만, 여러 자바스크립트 라이브러리에서
이런 식으로 할당 연산자를 사용하고 있기 때문에 동작 원리를 이해할 수 있어야 한다.
다만, 직접 코드를 작성할 땐 이런 방식을 사용하지 않기를 바란다.
이런 트릭을 사용하면 코드가 명확하지 않을 뿐만 아니라 가독성도 떨어지기 때문임.
9-2 할당 연산자 체이닝
여러개 연결 가능
let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
평가는 우측부터 진행됨. 그러니까 2+2 에 나온 결과가 a, b, c 에 순차적으로 할당됨.
c = 2 + 2;
b = c;
a = c;
그런데 되도록이면 연산자를 체이닝 하는것 보다
가독성을 위해 줄을 나눠 코드를 작성하는것을 권유함.
눈에 쉽게 들어오니까!
9-3 복합 할당 연산자
let n = 2;
n = n + 5;
n = n * 2;
let n = 2;
n += 5; // n은 7이 됩니다(n = n + 5와 동일).
n *= 2; // n은 14가 됩니다(n = n * 2와 동일).
alert( n ); // 14
/= 또는 -= 등의 연산지도 가능.
let n = 2;
n *= 3 + 5;
alert( n ); // 16 (*=의 우측이 먼저 평가되므로, 위 식은 n *= 8과 동일함.)
10. 증가, 감소 연산자
10-1 증가(increment)연산자 : ++ 변수를 1 증가시킨다
이 예문으로 이해 안갔던게 갔음!!
let count = 1
const preIncrement = ++count
// 증감연산자를 앞에 놓게 되면 아래 주석으로 처리한 두 줄의 코드와 같은 내용입니다.
// 먼저 자기 자신에게 1을 더해서 재할당 한 후, 이를 preIncrement 에 할당했다는 의미입니다.
// count = count + 1
// const preIncrement = count
console.log(`count: ${count}, preIncrement: ${preIncrement}`) // count: 2, preIncrement: 2
let count = 1
const postIncrement = count++
// 증감연산자를 뒤에 놓게 되면 아래 주석으로 처리한 두 줄의 코드와 같은 내용입니다.
// postIncrement에 자기 자신의 값을 먼저 할당하고, 이후에 1을 더해서 재할당합니다.
// const postIncrement = count
// count = count + 1
console.log(`count: ${count}, postIncrement: ${postIncrement}`) // count: 2, postIncrement: 1
***증감연산자를 활용에 count 의 값을 계속 증가시키고 다시 count에 할당하기때문에 const쓰면 에러남!***
let counter = 2;
counter++; // counter = counter + 1과 동일하게 동작한다. 하지만 식은 더 짧음.
alert( counter ); // 3
10-2 감소(decrement) 연산자 : -- 변수를 1 감소시킨다.
let counter = 2;
counter--; // counter = counter - 1과 동일하게 동작한다. 하지만 식은 더 짧음.
alert( counter ); // 1
***증가·감소 연산자는 변수에만 쓸 수 있음. 5++와 같이 값에 사용하려고 하면 에러가 발생***
10-3 전위형(prefix form) : ++counter와 같이 피연산자 앞에 올 때
10-4 후위형(postfix form) : counter++와 같이 피연산자 뒤에 올 때
후위형과 전위형은 피연산자인 counter를 1만큼 증가시켜 준다는 점에서 동일한 일을 한다.
두 형의 차이는 ++/--의 반환 값을 사용할 때 드러난다.
전위형은 증가·감소 후의 새로운 값을 반환하는 반면,
후위형은 증가·감소 전의 기존 값을 반환한다.
let counter = 1;
let a = ++counter; // (*)
alert(a); // 2
전위형, counter를 1 증가시키고(counter+1) a에 결과값을 할당하니까 alert(a) = 2
let counter = 1;
let a = counter++; // (*) ++counter를 counter++로 바꿈
alert(a); // 1
후위형, counter를 증가시키긴 하지만 증가 전, 기존값을 반환한다.
10-5 전위형과 후위형 정리
반환값을 사용하지 않는 경우라면, 전위형과 후위형엔 차이X ----->아래 연산 ++counter는 0아닌가?
let counter = 0;
counter++;
++counter;
alert( counter ); // 2, 위 두 라인은 동일한 연산을 수행한다.
값을 증가시키고 난 후, 증가한 값을 바로 사용하려면 전위형 증가 연산자를 사용하자.
let counter = 0;
alert( ++counter ); // 1
값을 증가시키지만, 증가 전의 기존값을 사용하려면 후위형 증가 연산자를 사용하자.
let counter = 0;
alert( counter++ ); // 0
11. 다른 연산자 사이의 증가*감소 연산자
++ 와 -- 연산자를 표현식 중간에 사용 가능함.
이때, 증가*감소 연산자의 우선순위는 다른 대부분의 산술 연산자보다 높기 때문에, 평가먼저 이뤄짐.
let counter = 1;
alert( 2 * ++counter ); // 4
<------> 비교해보자
let counter = 1;
alert( 2 * counter++ ); // counter++는 '기존'값을 반환하기 때문에 2가 출력된다.
가독성 좋은 코드 ( 코드 한줄엔, 특정 동작 하나만 작성하는게 좋음)
let counter = 1;
alert( 2 * counter );
counter++; //2
12. 비트 연산자(bitwise operator) : 인수를 32비트 정수로 변환하여 이진 연산을 수행한다.
- 비트 AND ( & )
- 비트 OR ( | )
- 비트 XOR ( ^ )
- 비트 NOT ( ~ )
- 왼쪽 시프트(LEFT SHIFT) ( << )
- 오른쪽 시프트(RIGHT SHIFT) ( >> )
- 부호 없는 오른쪽 시프트(ZERO-FILL RIGHT SHIFT) ( >>> )
비트 연산자는 저수준(2진 표현)에서 숫자를 다뤄야 할 때 쓰이므로 흔하게 쓰이진 않습니다. 웹 개발 시엔 이런 일이 자주 일어나지 않기 때문에 비트 연산자를 만날 일은 거의 없죠. 그렇긴 해도 암호를 다뤄야 할 땐 비트 연산자가 유용하기 때문에 때가 되면 MDN의 비트 연산자 문서를 보시는 걸 추천합니다. ------->뭔소리고
13. 쉼표 연산자(comma operator)
보기 힘들고, 특이한 연산자임. 코드를 짧게 쓰려는 의도로 가끔 사용됨.
쉼표 연산자 ,는 여러 표현식을 코드 한 줄에서 평가할 수 있게 해준다.
이때 표현식 각각이 모두 평가되지만, 마지막 표현식의 평가 결과만 반환되는 점에 유의하자.
let a = (1 + 2, 3 + 4);
alert( a ); // 7 (3 + 4의 결과)
1+2 결과를 버리고 3+4 결과만 a에 할당됨.
13-1 쉼표의 우선순위는 낮다
할당 연산자 = 보다 더 낮다.
그러다 보니 괄호가 중요함
괄호가 없으면 a = 1 + 2, 3 + 4에서 +가 먼저 수행되어 a = 3, 7이 된다.
할당 연산자 =는 쉼표 연산자보다 우선순위가 높기 때문에 a = 3이 먼저 실행되고,
나머지(7)는 무시된다. (a = 1 + 2), 3 + 4를 연산한 것처럼 될 거임.
/ 한 줄에서 세 개의 연산이 수행됨
for (a = 1, b = 3, c = a * b; a < 10; a++) {
...
}
여러 동작을 하나의 줄에서 처리하려는 복잡한 구조에서 사용된다고 함.
QQQQQQ여기 b가 왜 2인거지??? 1 아님????
let a = 1, b = 1;
et c = ++a; // ?
let d = b++; // ?
답은 다음과 같습니다.
- a = 2
- b = 2
- c = 2
- d = 1
let a = 1, b = 1;
alert( ++a ); // 2, 전위형은 증가 후의 값을 반환합니다.
alert( b++ ); // 1, 후위형은 증가 전의 값을 반환합니다.
alert( a ); // 2, 값이 1만큼 증가합니다.
alert( b ); // 2, 값이 1만큼 증가합니다.