본문으로 건너뛰기

이름표 다시 붙이기와 const

자바스크립트 목차첫 프로그램레슨 5 / 76

목차

이름은 값에 붙은 이름표입니다. 이름을 다른 값에 다시 붙이면 옛 값과의 연결은 끊기고, 한 값에는 이름이 여럿 붙을 수 있습니다. const로 만든 이름은 다시 붙일 수 없습니다.

변수를 값을 담는 상자로 생각하면, 새 값을 넣어도 옛 값이 남는다거나 두 이름이 서로 따라 바뀐다고 잘못 예측하기 쉽습니다. 자바스크립트에서 이름은 값을 담지 않고 값을 가리킬 뿐입니다. 이 그림을 지금 세워 두면, 뒤에서 배열을 배울 때 생각을 뒤집지 않아도 됩니다. 이 레슨에서는 규칙 3을 세웁니다.

10단계 중 1단계. 이름 x를 만든 뒤 다시 붙이는 코드입니다.

1다시 붙이면 옛 연결은 끊긴다

그림의 첫 코드는 이름 x를 만든 뒤 다시 붙입니다.

let x = 5;
x = 7;
console.log(x);
실행 결과
7

1번 줄이 이름 x를 만들어 값 5에 붙입니다. 2번 줄은 새 값 7을 만들고 x를 7에 다시 붙입니다. 이때 x와 5의 연결은 끊깁니다. 5가 7로 바뀐 것이 아닙니다. 5는 그대로 있지만 이제 5를 가리키는 이름이 없어, 코드에서 5를 다시 꺼낼 길이 없습니다. 그림은 이런 값을 점선 칸으로 남겨 '가리키는 이름 없음'이라고 적습니다. 3번 줄은 x가 지금 붙어 있는 값 7을 찍습니다.

2한 값에 이름이 여럿 붙는다

그림의 둘째 코드는 이름 둘을 씁니다. 1·2번 줄은 그림의 둘째 코드와 같습니다.

let a = 10;
let b = a;
console.log(a, b);
실행 결과
10 10

2번 줄 let b = a;도 대입이라 오른쪽부터 계산합니다(규칙 2). 오른쪽 a를 계산하면 a가 붙은 값 10이 나옵니다. 이때 새 값을 만들지 않습니다. 새 이름 b를 a가 붙은 바로 그 10에 붙입니다. 이제 값 10에는 이름표가 둘입니다. 그림은 값 칸 머리에 그 값을 가리키는 이름을 모두 적습니다. 10의 칸에는 a와 b가 함께 적힙니다.

3하나를 다시 붙여도 다른 이름은 그대로

그림의 둘째 코드 전체입니다.

let a = 10;
let b = a;
a = a + 1;
console.log(b);
실행 결과
10

3번 줄은 오른쪽 a + 1을 계산해 새 값 11을 만들고, a만 11에 다시 붙입니다. b는 10에 그대로 붙어 있어 4번 줄은 10을 찍습니다. b가 10 그대로인 것은 b가 a의 사본이라서가 아닙니다. 3번 줄이 a를 새 값에 다시 붙였을 뿐, b가 붙은 10은 건드리지 않았기 때문입니다. 그래서 이 레슨은 '값을 바꾼다' 대신 '다시 붙인다'라고 씁니다. 수는 제자리에서 바뀌는 일이 없어 a + 1은 늘 새 값을 만듭니다. 제자리에서 바뀌는 값은 7단원의 배열에서 만나는데, 그때는 사본으로 본 사람과 이름표로 본 사람의 예측이 갈립니다.

4const는 다시 붙이기를 막는다

const도 let처럼 이름을 새로 만듭니다. 다른 점은 그 이름을 다시 붙일 수 없다는 것입니다.

const price = 4000;
console.log(price);
price = 4500;
실행 결과
4000main.js:3price = 4500;      ^ TypeError: Assignment to constant variable.    at main.js:3:7

설명의 constant variable은 '다시 붙일 수 없는 이름'(상수)이라는 뜻으로, 그런 이름에 대입했다는 오류입니다. 실행 중 오류라 2번 줄의 4000은 찍혔고, 3번 줄에서 멈췄습니다. 다시 붙일 일이 없는 이름을 const로 만들어 두면, 실수로 다시 붙였을 때 오류로 알 수 있습니다. 그래서 2단원부터 예제는 다시 붙이지 않을 이름에 const를, 다시 붙일 이름에 let을 씁니다.

규칙 3. 이름은 값에 붙은 이름표입니다. 다시 붙이면 옛 연결은 끊기고, 한 값에 이름이 여럿 붙을 수 있습니다. const는 다시 붙이기만 막습니다.

예제

같은 이름에 대입이 세 번 이어집니다. 무엇이 찍힐지 먼저 적어 본 뒤 결과를 펼쳐 보세요.

let cups = 1;
cups = 2;
cups = cups + 1;
console.log(cups);
실행 결과 보기
실행 결과
3

예상과 다르면 그곳이 배울 곳입니다. 1, 2, 3이 모두 찍히거나 더해서 6이 찍힌다고 예상했다면, 이름을 값이 쌓이는 상자로 본 것입니다. 2번 줄이 cups를 2에 다시 붙이고, 3번 줄이 그 2에 1을 더한 새 값 3에 다시 붙입니다. 이름은 마지막에 붙은 값 하나만 가리킵니다(규칙 3).

커피 값이 내일부터 오릅니다. 오늘 값에 다른 이름을 붙여 두면, coffee를 새 값에 다시 붙여도 오늘 값을 꺼낼 수 있습니다. today는 다시 붙이지 않으니 const로 만듭니다.

let coffee = 4000;
const today = coffee;
coffee = 4500;
console.log('오늘', today);
console.log('내일', coffee);
실행 결과
오늘 4000
내일 4500

2번 줄이 today를 coffee와 같은 4000에 붙입니다. 3번 줄은 coffee만 새 값 4500에 다시 붙이므로 today는 4000에 그대로 남습니다.

자주 틀리는 곳

틀린 생각: 이름은 값을 담는 상자라서, 새 값을 넣어도 옛 값이 함께 남는다.

변수를 '값을 담는 상자'로 설명하는 자료도 있어 그렇게 그리게 됩니다. 다시 붙이면 옛 값과의 연결은 끊깁니다.

let score = 70;
score = 85;
console.log(score);
실행 결과
85

2번 줄이 score를 85에 다시 붙이는 순간 70과의 연결은 끊깁니다. 그래서 70 85도 155도 아닌 85가 찍힙니다.

맞는 규칙: 이름은 값에 붙은 이름표라, 다시 붙이면 옛 연결은 끊기고 마지막에 붙은 값 하나만 가리킵니다. 대입이 이어지면 줄마다 이름표를 옮겨 그리며 읽습니다(규칙 3).

틀린 생각: let b = a;는 a가 붙은 값의 사본을 하나 더 만들어 b에 준다.

뒤에서 a를 다시 붙여도 b가 따라 바뀌지 않으니, b가 따로 사본을 받은 것처럼 보입니다. let b = a;는 같은 값에 이름을 하나 더 붙일 뿐입니다.

let a = 10;
let b = a;
a = a + 1;
console.log(a, b);
실행 결과
11 10

b가 10으로 남은 것은 3번 줄이 a만 새 값 11에 다시 붙였기 때문입니다. b가 붙은 10은 아무도 건드리지 않았습니다. 배열처럼 제자리에서 바뀌는 값에서는 두 이름이 함께 바뀐 것으로 보이니, 그때 이 그림을 다시 꺼냅니다.

맞는 규칙: let b = a;는 새 값을 만들지 않고, a가 붙은 바로 그 값에 b를 하나 더 붙입니다. 그 뒤 a를 다시 붙여도 b는 원래 값에 그대로 붙어 있습니다(규칙 3).

틀린 생각: const는 값을 얼려서, 그 값에 붙은 다른 이름도 다시 붙일 수 없다.

const에 '바뀌지 않는'(constant)이라는 뜻이 있어 값이 얼어붙는 것처럼 읽힙니다. const가 묶는 것은 값이 아니라 그 이름표 하나입니다.

const a = 10;
let b = a;
b = 20;
console.log(a, b);
실행 결과
10 20

a와 b는 같은 값 10에 붙었지만, let으로 만든 b는 20에 다시 붙었습니다. const는 a를 다시 붙이는 일만 막습니다.

맞는 규칙: const는 그 이름을 다른 값에 다시 붙이지 못하게 할 뿐, 값을 얼리지 않습니다. 같은 값에 붙은 let 이름은 다시 붙일 수 있습니다(규칙 3).

확인 문제

1. 3절 코드의 1번 줄을 let a = 3;으로 바꿨습니다. 무엇이 찍힐까요?

let a = 3;
let b = a;
a = a + 1;
console.log(b);
힌트

2번 줄에서 b가 붙는 값을 먼저 정하고, 3번 줄에서 어느 이름이 옮겨 가는지 봅니다.

정답
실행 결과
3

2번 줄에서 b가 3에 붙고, 3번 줄은 a만 새 값 4에 다시 붙입니다. b는 3 그대로입니다. 흔한 오답은 4입니다. b가 이름 a를 따라 움직인다고 본 것입니다(규칙 3).

2. 실행 결과가 7 5가 되도록 ㉠~㉣을 위에서 아래로 놓으세요.

  • ㉠ console.log(x, y);
  • ㉡ x = 7;
  • ㉢ const y = x;
  • ㉣ let x = 5;

놓은 뒤에는 이것도 고르세요. ㉢이 ㉡보다 위에 와야 하는 까닭은 무엇일까요?

  • ① x가 7에 다시 붙기 전에, x가 붙은 5에 y를 붙여 두어야 하기 때문
  • ② const y = x;가 두 이름을 묶어, 뒤에서 x가 바뀌면 y도 따라 바뀌기 때문
  • ③ ㉡이 먼저 오면 x에 5와 7이 함께 남아 y가 둘 다 받기 때문
힌트

놓아 본 차례대로 줄마다 이름표를 그려, ㉠이 7 5를 찍는지 봅니다.

정답

㉣ ㉢ ㉡ ㉠ 차례이고, 까닭은 ①입니다. ㉡을 ㉢보다 먼저 두면 y도 7에 붙어 7 7이 찍힙니다.

  • ② 이름끼리 묶이지 않습니다. y는 그때 x가 가리키던 값 5에 붙고, 뒤에서 x를 다시 붙여도 y는 그대로입니다(규칙 3).
  • ③ 상자 생각입니다. x를 7에 다시 붙이면 5와의 연결은 끊깁니다(규칙 3).

3. 목표 걸음 수는 const로, 걸은 수는 let으로 만들었습니다. 무엇이 찍히고 어디서 멈추는지 실행 결과를 그대로 쓰세요. 오류 메시지는 …Error: 줄만 써도 됩니다.

const goal = 8000;
let walked = 3000;
walked = 9500;
console.log(walked);
goal = 10000;
console.log(goal);
힌트

다시 붙이는 이름마다 let으로 만들었는지 const로 만들었는지 봅니다(4절).

정답
실행 결과
9500main.js:5goal = 10000;     ^ TypeError: Assignment to constant variable.    at main.js:5:6

3번 줄은 let으로 만든 walked를 다시 붙여 문제가 없고, 4번 줄이 9500을 찍습니다. 5번 줄은 const로 만든 goal을 다시 붙이려 해 멈춥니다. 흔한 오답은 9500 다음 10000까지 쓴 답입니다. const도 let처럼 다시 붙일 수 있다고 본 것입니다. 아무것도 찍히지 않는다고 썼다면, 실행 중 오류를 문법 오류처럼 본 것입니다.

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 3절 코드(네 줄)를 저장해 돌립니다. 그다음 1번 줄의 let을 const로 바꾸면 무엇이 찍힐지 먼저 적고, 바꿔 돌려서 맞춰 봅니다. 저장하고 돌리는 법은 다음 레슨 내 컴퓨터에서 돌려 보기에 있습니다.

더 보기: 7단원의 '배열과 이름 둘'에서 두 이름이 한 배열을 가리킬 때 이 그림을 다시 씁니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

자바스크립트 목차로