[모던 JavaScript 튜토리얼] 22. 문자열
자바스크립트는 한 개의 단일 문자를 저장하기 위한 자료형이 별도로 존재하지 않고, 문자형이 없기에 문자형과 문자열을 구분하기 위한 따옴표와 쌍따옴표의 차이도 없다.
따옴표
자바스크립트엔 다음 세 개의 따옴표 종류가 있다.
- 작은따옴표(‘ ‘)
- 큰따옴표(“ “)
- 백틱(` `)
function sum(a, b) {
return a + b;
}
console.log(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
작은따옴표와 큰따옴표 둘의 차이는 없다. 백틱은 ES6에 새로 도입된 템플릿 리터럴(Template literal)
표기법이다. ${...}
로 감싸 백틱 안에 넣어주면 표현식을 문자열 중간에 삽입할 수 있도록 허용한다.
문자열의 길이
console.log("My\n".length); // 3
length
프로퍼티엔 문자열의 길이가 저장된다. \n 은 특수 문자 하나로 취급되기에, 문자열의 길이는 3이 된다.
특정 글자에 접근하기
let str = "hello";
console.log(str[0]); // h
console.log(str.charAt(0)); // h
대괄호를 사용해 배열처럼, 혹은 str.charAt(pos) 메서드를 호출해 접근한다.
let str = "hello";
console.log(str[1000]); // undefined
console.log(str.charAt(1000)); // "" (빈 문자열)
두 방식의 차이점은 없는 인덱스에 접근할 때 나타난다. []
는 undefined를, charAt
은 빈 문자열을 리턴한다.
문자열의 불변성
let str = "Hi";
str = str[0] + "ello";
console.log(str); // Hello
문자열은 할당 이후 문자에 접근해 수정할 수 없다. 도중에 변경을 원하면 전체를 교체해야 한다.
대소문자 변경하기
console.log("Hello"[0].toLowerCase()); // "h"
toUpperCase()
와 toLowerCase()
를 통해 문자열 전체를 각각 대문자, 소문자로 변경할 수 있다. 혹은 위와 같이 문자 하나만 변경하는 것도 가능하다.
부분 문자열 찾기
문자열에서 부분 문자열을 찾는 방법은 아래와 같다.
- indexOf 메서드를 사용
- 비트 연산자 NOT을 사용
- includes, startsWith, endsWith 메서드를 사용
indexOf 메서드
let str = "Widget with id";
console.log(str.indexOf("Widget")); // 0
console.log(str.indexOf("widget")); // -1
console.log(str.indexOf("id")); // 1
console.log(str.indexOf("id", 2)); // 12
str.indexOf(substr, pos)
는 문자열 str의 pos 위치에서 시작해, 부분 문자열 substr 이 위치하는 인덱스를 리턴한다. pos 는 생략이 가능하며, 생략할 시 맨 처음부터 검색을 시작한다.
부분 문자열이 존재하면 해당 시작 위치를, 존재하지 않는다면 -1을 리턴한다.
let str = "As sly as a fox, as strong as an ox";
let target = "as";
let pos = 0;
while (true) {
let foundPos = str.indexOf(target, pos);
if (foundPos == -1) break;
console.log(`위치: ${foundPos}`);
pos = foundPos + 1;
}
// let pos = -1;
//
// while ((pos = str.indexOf(target, pos + 1) != -1)) {
// console.log(`위치: ${pos}`);
// }
검색하고 싶은 부분 문자열을 모두 찾고 싶으면 위와 같이 작성하면 된다.
비트 연산자 NOT을 이용
비트연산자 NOT(~) 은 2진수 비트들로 표현된 피연산자의 모든 비트를 반전시킨다. 32비트의 signed integer로 숫자를 표현하는 자바스크립트의 특성상 n을 반전시킨 값 ~n
은 -(n+1)
이 된다.
let str = "Widget";
if (~str.indexOf("Widget")) {
console.log("찾았다!");
}
즉, 부호 있는 32비트 정수 n 중 ~n 을 0으로 만드는 경우는 n이 -1일 때가 유일하다. 검색이 되지 않을 경우 -1을 리턴하는 indexOf 메서드에 응용해 부분 문자열을 검사할 수 있다.
includes, startsWith, endsWith
console.log("Widget with id".includes("Widget")); // true
console.log("Hello".includes("Bye")); // false
console.log("Widget".includes("id", 3)); // false
str.includes(substr, pos)
는 부분 문자열의 인덱스 위치 정보는 필요하지 않고, 포함하는 여부만 알고 싶을 때 적합하다. pos를 주면, 해당 인덱스부터 검사를 실행한다.
console.log("Widget".startsWith("Wid")); // true
console.log("Widget".endsWith("get")); // true
str.startsWidth
는 str 이 특정 문자열로 시작하는지를, str.endsWith
는 str 이 특정 문자열로 끝나는지를 확인할 때 사용한다.
부분 문자열 추출하기
아래는 slice
, substring
, substr
에 대한 정리다. 문서에서는 slice
가 가장 유연하니, slice만 외워놓고 사용해도 충분할 거라고 한다.
str.slice(start [, end])
str = "stringify";
console.log(str.slice(0, 5)); // strin
console.log(str.slice(0, 1)); // s
console.log(str.slice(-4, -1)); // gif
end는 생략할 수 있으며, 생략 시 start 부터 끝까지, 명실할 시 start 부터 end 까지를 반환한다. 위 마지막 예처럼 음수 인덱스를 사용할 수 있다.
str.substring(start [, end])
str = "stringify";
console.log(str.substring(2, 6)); // "ring"
console.log(str.substring(6, 2)); // "ring"
console.log(str.substring(-4, -1)); // ""
console.log(str.slice(6, 2)); // ""
slice
와의 차이점
- 음수 인덱스를 허용하지 않는다. (음수 인덱스 사용시 0으로 처리된다.)
- start 가 end 보다 커도 된다.
str.substr(start [, length])
str = "stringify";
console.log(str.substr(2, 4)); // ring
console.log(str.substr(-4, 2)); // gi
substr 은 끝 위치 대신 길이를 기준으로 문자열을 추출할 수 있다. start 로 음수 인덱스를 허용한다.
문자열 비교하기
str.codePointAt(pos)
console.log("a".codePointAt(0)); // 97
console.log("A".codePointAt(0)); // 65
pos
에 위치한 글자의 코드를 반환한다.
String.fromCodePoint(code)
console.log(String.fromCodePoint(97)); // "a"
console.log(String.fromCodePoint(65)); // "A"
code
에 대응한 글자를 만들어 준다.
charCodeAt()과 codePointAt() 차이
let str = "😀";
let cca = str.charCodeAt(0);
let cpa = str.codePointAt(0);
console.log(cca); // 55357
console.log(cpa); // 128512
console.log(cca.toString(16)); // "d83d"
console.log(cpa.toString(16)); // "1f600"
console.log(String.fromCharCode(cca)); // �
console.log(String.fromCodePoint(cpa)); // 😀
charCodeAt()
은 UTF-8로 표현 가능한 문자에 사용하는 것이, codePointAt()
은 UTF-16로 표현 가능한 문자에 사용하는 것이 적합하다.
str.localeCompare(str2)
let words = ["car", "banana", "cat", "apple", "ball", "ant"];
words.sort((a, b) => a.localeCompare(b));
console.log(words); // ["ant", "apple", "ball", "banana", "car", "cat"]
str
을 str2
에 비교해 작은지, 같은지, 큰지를 나타내준다. 이를 compare function으로 사용해 사전순 정렬이 가능하다.
댓글남기기