[모던 JavaScript 튜토리얼] 22. 문자열

3 분 소요

본문 바로가기


자바스크립트는 한 개의 단일 문자를 저장하기 위한 자료형이 별도로 존재하지 않고, 문자형이 없기에 문자형과 문자열을 구분하기 위한 따옴표와 쌍따옴표의 차이도 없다.


따옴표

자바스크립트엔 다음 세 개의 따옴표 종류가 있다.

  1. 작은따옴표(‘ ‘)
  2. 큰따옴표(“ “)
  3. 백틱(` `)


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() 를 통해 문자열 전체를 각각 대문자, 소문자로 변경할 수 있다. 혹은 위와 같이 문자 하나만 변경하는 것도 가능하다.


부분 문자열 찾기

문자열에서 부분 문자열을 찾는 방법은 아래와 같다.

  1. indexOf 메서드를 사용
  2. 비트 연산자 NOT을 사용
  3. 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) 는 문자열 strpos 위치에서 시작해, 부분 문자열 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 와의 차이점

  1. 음수 인덱스를 허용하지 않는다. (음수 인덱스 사용시 0으로 처리된다.)
  2. 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"]

strstr2 에 비교해 작은지, 같은지, 큰지를 나타내준다. 이를 compare function으로 사용해 사전순 정렬이 가능하다.

댓글남기기