전위연산자 & 후위연산자 (+엘리스 토끼굴에 빠진 var)
사실 이건 중요한건 아닌데 모던 js 읽을때 헷갈렸던 부분이다.
# 후위연산자
let num = 1;
console.log(num++, " #A"); // 1 #A
console.log(num, " #B"); // 2 #B
일단 num에 1을 할당하고 여기에 후위연산자를 붙여서 콘솔로 찍어보면
A부분에 1로 뜬다. 응? 난 분명 1을 증가시켰는데?
그래서 B에서 다시 num을 참조하려고 하면 증가된 2를 볼 수 있다.
# 전위연산자
let num = 1;
console.log(++num, " #A"); // 2 #A
console.log(num, " #B"); // 2 #B
이곳에선 결과가 다르게 뜬다.
# 두 차이는 무엇일까?
- 후위 연산자는 원래 num의 값을 가지고 있어서 참조시에는 원래 num의 값을 출력한다.
그 후에 num을 증가시킨다.
- 전위 연산자는 증가시키고 바로 할당을 해버린다. 따라서 증가된 num의 값을 출력한다.
# while 반복문에서 후위증가연산자
let i = 1;
while (i) {
if (i < 3) {
console.log(i++);
} else {
break;
}
}
console.log(i, "마지막 i값"); //3
while문의 알고리즘으로 생각해보자.
- 처음 i는 1이다.
- while(i)조건에서 i 는 1이므로 true이다.
- if문 조건에서 i 는 1이고 3보다 작다.
- 콘솔에 i++를 찍는데 후위연산자이므로 증가되기전인 1값을 출력한다. (출력!)
- 출력후 i값을 증가시켜 2가된다.
- while(i)조건에서 i 는 2이므로 true이다.
- if문 조건에서 i는 2이고 3보다 작다.
- 콘솔에 i++를 찍는데 후위연산자이므로 증가되기전인 2값을 출력한다. (출력!)
- 출력후 i값을 증가시켜 3이된다.
- while(i)조건에서 i 는 3이므로 true이다.
- if문 조건에서 i는 3이고 3보다 작지않다
- else문으로 넘어간다. (break!)
- 마지막으로 스코프 밖에서 i를 찍어보면 3이 나온다.(출력!)
# while 반복문에서 전위증가연산자
let i = 1;
while (i) {
if (i < 3) {
console.log(++i);
} else {
break;
}
}
console.log(i, "마지막 i값"); //3
- 처음 i는 1이다.
- while(i)조건에서 i 는 1이므로 true이다.
- if문 조건에서 i 는 1이고 3보다 작다.
- 콘솔에 ++i를 찍는데 전위연산자이므로 이미 증가되었다. 1에서 1 증가된 2값을 출력한다. (출력!)
- while(i)조건에서 i 는 2이므로 true이다.
- if문 조건에서 i는 2이고 3보다 작다.
- 콘솔에 ++i를 찍는데 전위연산자이므로 이미 증가되었다. 2에서 1 증가된 3값을 출력한다. (출력!)
- while(i)조건에서 i 는 3이므로 true이다.
- if문 조건에서 i는 3이고 3보다 작지않다
- else문으로 넘어간다. (break!)
- 마지막으로 스코프 밖에서 i를 찍어보면 3이 나온다. (출력!)
# for 반복문에서 후위증가연산자 (함정)
for (let i = 0; i < 3; i++) {
console.log(i);
}
console.log(i, "마지막 i값");
이번엔 for 반복문에서 알고리즘을 생각해보자.
결과는 어떻게될까?
참조에러 뜹니다..
얕은 함정을 파봤다. 왜 var보다 let으로 선언문을 써야하는지 나온다.
이런 에러가 뜨면 설명할 줄 알아야 한다.
설명을 위해 for반복문에서 let을 var로 바꿔보겠다.
for (var i = 0; i < 3; i++) {
console.log(i);
}
console.log(i, "마지막 i값");
정상적으로 작동된다.
왜일까?
- let으로 선언한 i값의 경우 스코프(범위)
위 설명처럼 let으로 선언한 변수는 스코프안에서만 활동할 수 있다.
때문에 for반복문 스코프 안에서 참조를 하려고 한다면 정상작동을 한다.
그러나 반복문 스코프 밖에서 i를 찍으려는 저 코드가 있는 스코프는 전역스코프다.
이 전역스코프에서는 i를 선언하지 않았기때문에 참조할 i가 없다.
때문에 reference error가 뜬것이다.
for (let i = 0; i < 3; i++) {
console.log(i);
}
그래서 저 밖에서 i참조하려는 코드를 지우면 정상 작동한다.
- var로 선언한 i값의 경우 스코프(범위)
var로 선언하는 변수의 경우 블록스코프를 무시한다.
블록스코프는 일반적인 스코프 for반복문 스코프, 조건문 스코프 다 통틀어서 적용된다.
때문에 블록안에서 var로 선언한 변수는 전역변수가 되어버린다..ㄷㄷ
이게 무서운게 코드를 수만줄 쓰다보면 변수이름을 똑같이 해버리는 실수를 가끔 하게되는데
스코프를 넘나드는 난봉꾼 변수가 있으면 에러가 터져도 찾기 졸라 힘들게된다.
++ var로 선언한 변수는 블록이 몇개로 감싸져 있든 다무시함
위 사진은 j가 반복문 스코프안에 조건문 스코프로 두번이나 감쌌지만 전역스코프에서 j를 참조한다 ㄷㄷ
때문에 var를 안쓰는 이유중 한가지가 이거다.
++ 참고로 블록스코프를 무시하는것이지 함수스코프는 무시하지않는다.
reference에러뜸
말이 길었다. 왜 es6부터 var말고 let쓰라는지 이유중 중요한 하나가 이거다.
암튼 후위연산자의 for반복문 알고리즘을 다시 보자
# for 반복문에서 후위증가연산자 (찐)
for (let i = 0; i < 3; i++) {
console.log(i);
}
- 맨처음 i는 0이다.
- for 반복문 조건에서 i 0은 3보다 작은가? true
- 콘솔로 i를 출력(0)한다 (출력!)
- i의 값을 증가시킨다. 0 > 1, 여기서 i++(0)값자체는 참조되지 않는다.
- i의 값이 1이 되었다.
- for 반복문 조건에서 i 1은 3보다 작은가? true
- 콘솔로 i를 출력(1)한다 (출력!)
- i의 값을 증가시킨다. 1 > 2, 여기서 i++(1)값자체는 참조되지 않는다.
- i의 값이 2가 되었다.
- for 반복문 조건에서 i 2는 3보다 작은가? true
- 콘솔로 i를 출력(2)한다 (출력!)
- i의 값을 증가시킨다. 2 > 3, 여기서 i++(2)값자체는 참조되지 않는다.
- i의 값이 3이 되었다.
- for 반복문 조건에서 i 3은 3보다 작은가? false
- 끝
# for 반복문에서 전위증가연산자
for (let i = 0; i < 3; ++i) {
console.log(i);
}
- 맨처음 i는 0이다.
- for 반복문 조건에서 i 0은 3보다 작은가? true
- 콘솔로 i를 출력(0)한다 (출력!)
- i의 값을 증가시킨다. 0 > 1
- i의 값이 1이 되었다.
- for 반복문 조건에서 i 1은 3보다 작은가? true
- 콘솔로 i를 출력(1)한다 (출력!)
- i의 값을 증가시킨다. 1 > 2
- i의 값이 2가 되었다.
- for 반복문 조건에서 i 2는 3보다 작은가? true
- 콘솔로 i를 출력(2)한다 (출력!)
- i의 값을 증가시킨다. 2 > 3
- i의 값이 3이 되었다.
- for 반복문 조건에서 i 3은 3보다 작은가? false
- 끝
둘다 똑같은 출력을 뱉는다.
전위 후위연산자는 크게 중요하지 않는것같다..
근데 모던자바스크립트 읽을때 이해안되서 좀 정확히 하고싶어서 다시 봤다.
사실 여기서 var과 let의 스코프차이가 엄청 중요하다.
끗