변수 — 값에 이름을 붙여 보관한다
Article
숫자 하나를 계산했다고 하자. 그 결과를 나중에 또 쓰려면 머릿속 대신 프로그램 안 어딘가에 적어둬야 한다.
값을 담아두고 이름을 붙여 다시 꺼내 쓰는 상자. 그게 변수다.
이름을 붙인다는 것
먼저 변수 없이 코드를 써본다.
console.log(1200 * 3);
console.log(1200 * 3 * 0.1);
1200이 뭔지 알 수 없고, 값이 바뀌면 두 군데를 다 고쳐야 한다. 변수를 쓰면 이렇게 된다.
const price = 1200;
const count = 3;
const total = price * count;
console.log(total);
console.log(total * 0.1);
- 3600
- 360.00000000000006
읽기 쉬워졌고, 가격이 바뀌어도 한 줄만 고치면 된다.
선언과 할당
변수를 만드는 일은 두 단계로 나뉜다.
- 01
선언 (declaration)
이름을 만든다. 아직 값은 없다.
let name; - 02
할당 (assignment)
만들어둔 이름에 값을 넣는다.
=는 "같다"가 아니라 "넣는다"는 뜻이다.name = "준호"; - 03
한 번에 하기
보통은 선언과 할당을 붙여서 쓴다.
let name = "준호";
= 기호를 수학에서처럼 "같다"로 읽으면 곧 혼란에 빠진다. 아래 코드를 보자.
let count = 1;
count = count + 1;
console.log(count);
- 2
수학이라면 count = count + 1은 말이 안 된다. 하지만 자바스크립트에서 이 줄은 "오른쪽을 계산해서 왼쪽에 넣어라"는 명령이다. 오른쪽 count + 1이 먼저 2가 되고, 그 2가 count에 들어간다.
메모리 상태로 보면 이렇다.
이름표가 붙은 상자에 값이 들어 있다
- price
- 1200
- count
- 2
- name
- "준호"
이름 짓는 규칙
변수 이름은 아무렇게나 지을 수 없다. 지켜야 하는 규칙과, 지키면 좋은 관습이 있다.
| 예시 | 가능 여부 | 이유 |
|---|---|---|
| userName | 가능 | 권장되는 형태 |
| user_name | 가능 | 동작하지만 자바스크립트에서는 덜 쓴다 |
| _count | 가능 | 밑줄과 $ 로 시작할 수 있다 |
| 1stPlace | 불가능 | 숫자로 시작할 수 없다 |
| user name | 불가능 | 공백을 넣을 수 없다 |
| let | 불가능 | 예약어는 쓸 수 없다 |
관습적으로 자바스크립트는 카멜 케이스를 쓴다. 첫 단어는 소문자로, 이어지는 단어의 첫 글자는 대문자로 붙인다. userName, totalPrice, isLoggedIn 같은 식이다.
그리고 대소문자를 구분한다. name과 Name은 완전히 다른 변수다.
let, const, var
변수를 만드는 키워드가 세 개다. 왜 셋이나 되는지부터 알아야 한다.
원래는 var 하나뿐이었다. 그런데 문제가 많아서, 2015년에 나온 ES6에서 let과 const가 추가됐다. 지금은 var를 쓸 이유가 거의 없다.
const
기본으로 쓴다
- 재할당 불가
- 재선언 불가
- 블록 스코프
- 선언과 동시에 값을 넣어야 한다
let
값이 바뀔 때만
- 재할당 가능
- 재선언 불가
- 블록 스코프
- 값 없이 선언할 수 있다
var
쓰지 않는다
- 재할당 가능
- 재선언 가능 — 사고의 원인
- 함수 스코프 — 예상을 벗어난다
- 옛날 코드에서만 만난다
재할당
let은 값을 다시 넣을 수 있고, const는 없다.
let score = 10;
score = 20;
console.log(score);
const limit = 100;
limit = 200;
- 20
- TypeError: Assignment to constant variable.
const는 "상수(constant)"의 줄임말이다. 한 번 정하면 바꾸지 않겠다는 선언이다.
재선언
같은 이름으로 변수를 또 만드는 것이다. var만 이걸 허용한다.
var user = "민수";
var user = "지영";
console.log(user);
- 지영
아무 경고 없이 덮어써진다. 코드가 길어지면 어딘가에서 같은 이름을 또 선언했는지 알아채기 어렵고, 값이 조용히 바뀐다.
let으로 같은 걸 하면 즉시 막아준다.
let user = "민수";
let user = "지영";
- SyntaxError: Identifier 'user' has already been declared
에러가 나는 쪽이 더 좋은 동작이다. 실수를 실행 전에 잡아준다.
스코프
세 번째 차이는 변수가 살아 있는 범위다. 중괄호 { } 안에서 선언한 변수가 바깥에서도 보이는지의 문제다.
if (true) {
var a = "var 로 선언";
let b = "let 으로 선언";
}
console.log(a);
console.log(b);
- var 로 선언
- ReferenceError: b is not defined
var는 중괄호를 무시하고 바깥으로 새어나온다. let과 const는 중괄호 안에 갇힌다. 후자가 훨씬 예측하기 쉽다.
그래서 뭘 써야 하나
규칙은 단순하다.
- 일단 const대부분 여기서 끝난다
- 값을 바꿔야 하면 let반복문 카운터 등
- var 는 안 쓴다옛날 코드에서 읽을 줄만 알면 된다
기본을 const로 두면 좋은 점이 있다. 이 값은 안 바뀐다는 사실이 코드에 드러난다. 나중에 코드를 읽는 사람이 그 변수를 추적하지 않아도 된다.
const 는 값을 얼려버리는 게 아니다
마지막으로 가장 많이 오해하는 부분이다.
배열이나 객체를 const로 선언하면 이런 일이 벌어진다.
const numbers = [1, 2, 3];
numbers.push(4);
console.log(numbers);
numbers = [9, 9];
- [1, 2, 3, 4]
- TypeError: Assignment to constant variable.
배열에 값을 추가하는 건 된다. 하지만 numbers에 아예 새 배열을 넣는 건 막힌다.
const가 지키는 건 상자와 이름의 연결이지, 상자 안에 든 값이 아니다. 배열은 상자에 직접 들어 있지 않고, 상자에는 "배열이 있는 위치"만 적혀 있다.
위치를 적어둔 상자는 잠겼지만, 그 위치에 있는 배열은 열려 있다
- limit
- 100
- numbers
- 0x1a2b
- [1, 2, 3, 4]
지금은 완전히 이해하지 못해도 괜찮다. 4강 자료형에서 원시 타입과 참조 타입을 구분하고 나면 이 그림이 저절로 풀린다.
정리하면
- 변수는 값에 이름을 붙여 보관하는 상자다.
=는 "오른쪽 값을 왼쪽에 넣어라"는 뜻이지 "같다"는 뜻이 아니다.const를 기본으로 쓰고, 재할당이 필요할 때만let을 쓴다.var는 쓰지 않는다.const는 재할당을 막을 뿐, 배열이나 객체의 내용까지 얼리지는 않는다.
다음 강의에서는 상자에 담기는 값의 종류를 본다. 숫자, 글자, 참/거짓 그리고 헷갈리기로 유명한 null과 undefined까지.