메서드(method)는 값 뒤에 점을 찍고 부르는, 그 값의 종류가 가진 기능입니다. toUpperCase()·trim()·replaceAll() 같은 문자열 메서드는 원래 문자열을 바꾸지 않고 새 문자열을 만들어 돌려주고, includes()는 글이 들어 있는지를 true·false로 알려 줍니다.
손님이 친 쿠폰 코드에는 앞뒤 빈칸이 끼거나 소문자가 섞여 있곤 합니다. 쓰기 전에 다듬어야 합니다.
그런데 쿠폰 코드에 trim()을 부르기만 하고 다듬어졌다고 생각하면, 다듬지 않은 값을 그대로 쓰게 됩니다. 메서드가 만든 새 값은 이름을 다시 붙여야 남습니다.
이름은 값에 붙은 이름표라는 규칙 3을 문자열 메서드에서 다시 봅니다.
1메서드는 새 문자열을 만든다
s.toUpperCase()는 s가 가리키는 문자열을 대문자로 적은 새 문자열을 만듭니다. 새 값을 쓰려면 이름을 붙입니다. 이름을 따로 붙이면 원래 값과 새 값이 둘 다 남습니다.
const s = 'cat';
const big = s.toUpperCase();
console.log(s);
console.log(big);
console.log(big.toLowerCase());
cat
CAT
cattoLowerCase()는 거꾸로 소문자로 적은 새 문자열을 만듭니다. 메서드는 부르는 것이라 이름 뒤의 괄호를 꼭 씁니다. 괄호 없이 쓰는 .length(속성)와 다릅니다.
문자열은 한 번 만들면 바꿀 수 없는 값입니다. 그래서 문자열 메서드는 원래 문자열을 바꾸지 않고, 바꾼 모양이 필요하면 새 문자열을 만들어 돌려줍니다.
2다시 붙여야 바뀐다
같은 이름으로 결과를 쓰고 싶으면, 메서드가 만든 새 값에 그 이름을 다시 붙입니다.
let s = 'cat';
s = s.toUpperCase();
console.log(s);
CAT2번 줄은 오른쪽 s.toUpperCase()를 먼저 계산해 새 값 'CAT'을 만들고(규칙 2), 이름 s를 그 값으로 옮겨 붙입니다(규칙 3). 'cat'은 가리키는 이름이 없어집니다.
'cat'이 'CAT'으로 바뀐 것이 아니라, 이름표 s가 새 값으로 옮겨 간 것입니다. 다시 붙일 이름이라 let으로 만들었습니다. const로 만든 이름이면 다시 붙일 수 없어 2번 줄이 TypeError로 멈춥니다.
3trim·replaceAll·includes
trim()은 맨 앞과 맨 뒤의 빈칸을 뗀 새 문자열을 만듭니다. 빈칸이 눈에 보이게 앞뒤에 대괄호를 붙여 찍었습니다.
const text = ' 커피 두 잔 ';
console.log(`[${text}]`);
console.log(`[${text.trim()}]`);
[ 커피 두 잔 ]
[커피 두 잔]trim()은 양 끝의 빈칸만 뗍니다. '커피'와 '두' 사이 같은 가운데 빈칸은 그대로입니다.
replaceAll(찾을 글자, 바꿀 글자)는 찾은 곳을 모두 바꾼 새 문자열을, includes(찾을 글자)는 그 글자가 들어 있으면 true, 없으면 false를 돌려줍니다.
let tel = '010-1234-5678';
console.log(tel.includes('-'));
tel = tel.replaceAll('-', '');
console.log(tel);
console.log(tel.includes('-'));
true
01012345678
false3번 줄은 '-' 두 개를 모두 빈 문자열로 바꾼 새 값에 tel을 다시 붙입니다. 그래서 2번 줄에서 true였던 includes('-')가 5번 줄에서는 false입니다.
includes()가 돌려주는 true·false는 불리언 값이고, 4단원에서 갈래를 고를 때 씁니다.
replaceAll()과 이름이 닮은 replace()도 찾은 글자를 바꾼 새 문자열을 만듭니다. 아래 코드는 무엇을 찍을까요? 답을 정한 뒤 펼쳐 보세요.
const s = 'a-b-c';
console.log(s.replace('-', ''));
실행 결과 보기
ab-c예상과 다르면 그곳이 배울 곳입니다.
replace()는 처음 찾은 '-' 하나만 지운 새 문자열을 만듭니다. 찾은 곳을 모두 바꾸려면 replaceAll()을 씁니다.
4문자열 한 칸은 바꿀 수 없다
자리 번호로 한 글자를 꺼낼 수는 있지만, 그 자리에 다른 글자를 대입할 수는 없습니다.
let s = 'cat';
s[0] = 'b';
console.log(s);
main.js:2s[0] = 'b'; ^ TypeError: Cannot assign to read only property '0' of string 'cat' at main.js:2:6TypeError 줄의 설명은 '문자열 cat의 읽기 전용 속성 0에 대입할 수 없다', 곧 문자열의 0번 칸은 바꿀 수 없다는 뜻입니다.
한 글자를 바꾼 문자열이 필요하면 새 문자열을 만들어 이름을 다시 붙입니다. s = 'b' + s.slice(1);이면 s는 'bat'에 붙습니다.
내 컴퓨터에서 이 코드가 오류 없이 cat을 찍는다면 설정이 레슨과 다른 옛 방식입니다. 내 컴퓨터에서 돌려 보기의 설정 확인 줄이 undefined를 찍는지 봅니다.
예제
손님이 친 쿠폰 코드 ' cf-07 '을 다듬습니다. 빈칸을 떼고, 대문자로 바꾸고, '-'를 지운 뒤 'CF'가 들어 있는 쿠폰인지 봅니다. 줄마다 메서드가 만든 새 값에 쿠폰 코드의 이름 key를 다시 붙입니다.
let key = ' cf-07 ';
key = key.trim();
key = key.toUpperCase();
key = key.replaceAll('-', '');
console.log(key);
console.log(key.length);
console.log(key.includes('CF'));
CF07
4
true2번 줄에서 'cf-07', 3번 줄에서 'CF-07', 4번 줄에서 'CF07'이 새로 만들어지고, 그때마다 key가 새 값으로 옮겨 붙습니다. 처음의 ' cf-07 '은 바뀌지 않았습니다. key가 더는 가리키지 않을 뿐입니다.
7번 줄의 includes()는 대문자로 바꾼 뒤라 'CF'를 찾습니다.
과목 끝의 할 일 앱에서도 입력한 할 일 글의 앞뒤 빈칸을 trim()으로 지우고, '전체 3개 중 2개 남음' 같은 개수 문장을 템플릿 문자열로 만듭니다.
자주 틀리는 곳
틀린 생각: 메서드를 부르기만 하면 그 문자열이 바뀐다.
s 뒤에 점을 찍어 부르니 s.toUpperCase() 한 줄로 s가 대문자가 될 것 같지만, 메서드는 새 문자열을 만들 뿐입니다.
let s = 'cat';
s.toUpperCase();
console.log(s);
s = s.toUpperCase();
console.log(s);
cat
CAT2번 줄이 만든 'CAT'에는 아무 이름도 붙지 않아 3번 줄은 그대로 cat을 찍습니다. 4번 줄에서 이름 s를 새 값으로 옮겨 붙인 뒤에야 CAT이 찍힙니다.
맞는 규칙: 문자열 메서드는 원래 문자열을 바꾸지 않고 새 값을 만들어 돌려줍니다. 그 결과를 쓰려면 s = s.toUpperCase()처럼 이름을 새 값에 다시 붙입니다(규칙 3).
틀린 생각: replace()도 찾은 곳을 모두 바꾼다.
이름이 '바꾸기'라 모두 바꿀 것 같지만, replace()는 처음 찾은 하나만 바꿉니다.
let tel = '010-1234-5678';
tel = tel.replace('-', '');
console.log(tel);
0101234-5678첫 '-'만 빠지고 둘째 '-'는 남았습니다. 3절처럼 replaceAll()을 쓰면 01012345678입니다.
맞는 규칙: replace()는 처음 찾은 하나만, replaceAll()은 찾은 곳을 모두 바꾼 새 문자열을 만듭니다. 모두 바꿀 때는 replaceAll()을 씁니다.
틀린 생각: trim()은 가운데 빈칸까지 뗀다.
빈칸을 떼는 메서드라 모든 빈칸이 사라질 것 같지만, 3절처럼 trim()은 양 끝만 봅니다. ' 커피 두 잔 '은 '커피 두 잔'이 될 뿐, 가운데 빈칸 둘은 남습니다.
맞는 규칙: trim()은 맨 앞과 맨 뒤의 빈칸만 뗀 새 문자열을 만듭니다. 가운데 빈칸까지 지우려면 replaceAll(' ', '')를 씁니다.
틀린 생각: includes()는 대문자와 소문자를 가리지 않는다.
사람에게 Cat과 cat은 같은 낱말이지만, includes()는 글자를 그대로 견줍니다.
let s = 'Cat';
console.log(s.includes('cat'));
s = s.toLowerCase();
console.log(s.includes('cat'));
false
true2번 줄은 대문자 C가 달라 false입니다. 3번 줄에서 s를 소문자로 바꾼 새 값에 다시 붙이고 찾으면 true입니다.
맞는 규칙: includes()는 대문자와 소문자를 다른 글자로 봅니다. 가리지 않고 찾으려면 양쪽을 toLowerCase()로 맞춘 뒤 찾습니다.
확인 문제
1. 예제의 1번 줄을 let key = ' ab-12-c ';로 바꿨습니다. 무엇이 찍힐까요? 세 줄을 글자 그대로 쓰세요.
let key = ' ab-12-c ';
key = key.trim();
key = key.toUpperCase();
key = key.replaceAll('-', '');
console.log(key);
console.log(key.length);
console.log(key.includes('CF'));
힌트
2~4번 줄을 한 줄씩 따라가며 key가 가리키는 값을 적어 보세요.
정답
AB12C
5
false'ab-12-c' → 'AB-12-C' → 'AB12C' 차례로 새 값이 만들어지고 key가 옮겨 붙습니다. replaceAll()은 '-'를 모두 지웁니다. 'AB12C'에는 'CF'가 없어 false입니다.
흔한 오답은 첫 줄의 AB12-C입니다. 처음 찾은 '-' 하나만 지운다고 본 것입니다. 하나만 지우는 것은 replace()입니다.
2. 다음 코드가 CAT을 찍도록 빈칸을 채우세요.
let s = 'cat';
____ s.toUpperCase();
console.log(s);
힌트
3번 줄이 찍을 때 s가 어느 값에 붙어 있는지 1번 줄부터 따라가 보세요.
정답
s =입니다.
let s = 'cat';
s = s.toUpperCase();
console.log(s);CATs.toUpperCase()가 만든 새 값 'CAT'에 이름 s를 다시 붙입니다.
흔한 오답은 빈칸을 비워 두는 것입니다. 그러면 새 값이 버려지고 cat이 찍힙니다. let을 다시 붙인 let s =는 같은 이름을 두 번 만들어 SyntaxError로 멈춥니다.
3. 장보기 목록의 품목을 다듬습니다. 무엇이 찍힐까요? 글자 그대로 쓰세요.
let item = ' apple ';
item.trim();
item = item.toUpperCase();
console.log(`[${item}]`);
힌트
메서드 줄마다 결과에 이름이 다시 붙는지 보세요. 2번 줄과 3번 줄이 다릅니다.
정답
[ APPLE ]2번 줄의 trim()이 만든 'apple'에는 아무 이름도 붙지 않아 버려집니다. 3번 줄은 앞뒤 빈칸이 그대로인 ' apple '로 대문자 새 값을 만들고, 그 값에 item을 다시 붙입니다.
흔한 오답은 [APPLE]입니다. 2번 줄만으로 item이 다듬어졌다고 본 것입니다.
컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요.
2절의 코드(세 줄)를 main.js에 저장해 돌립니다. 그다음 2번 줄 s = s.toUpperCase();에서 앞의 s = 를 빼면 무엇이 찍힐지 먼저 적고, 바꿔 돌려서 맞춰 봅니다.
저장하고 돌리는 법은 내 컴퓨터에서 돌려 보기에 있습니다.