자바스크립트에서 문자열은 페이지 인코딩 방식과 상관없이 항상 UTF-16 형식을 따른다.
따옴표
따옴표의 종류가 무엇이 있었는지 상기해보자
문자열은 작은 따옴표나 큰따옴표,백틱으로 감쌀 수 있다.
let single = '작은따옴표';
let double = "큰따옴표";
let backticks = `백틱`;
작은따옴표와 큰 따옴표는 기능상 차이가 없다.
하지만 백틱엔 특별한 기능이 있다. 표현식을 ${...}으로 감싸고 이를 백틱으로 감싼 문자열 중간에 넣으면 문자열 중간에 쉽게 삽입할 수 있다. -> 이러한 방식을 템플릿 리터럴 이라고 부른다.
function sum(a, b) {
return a + b;
}
alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
let guestList = `손님:
* John
* Pete
* Mary
`;
alert(guestList); // 손님 리스트를 여러 줄에 걸쳐 작성함
작은 따옴표나 큰따옴표를 사용하면 위와 같은 방식으로 여러 줄짜리 문자열을 만들수없다.
let guestList = "손님: // Error: Invalid or unexpected token
* John";
작은 따옴표나 큰따옴표로 문자열 표현하는 방식은 자바 스크립트가 만들어졌을 때부터 있었다
백틱은 그 이후에 등장한 분법이기 때문에 따옴표보다 다양한 기능을 제공한다.
백틱은 템플릿 함수 에서도 사용된다. func'string'같이 첫 번째 백틱 바로 앞에 함수 이름(func)을 써주면 이 함수는 백틱 안의 문자열 조각이나 표현식 평가 결과를 인수로 받아 자동으로 호출된다. -> 이런 기능을 태그드 템플릿 이라고 부른다.
태그드 템플릿을 사용하면 사용자 지정 템플릿에 맞는 문자열을 쉽게 만들 수 있다.
특수 기호
'줄 바꿈 문자라 불리는 특수기호 \n을 사용하면 작은따옴표나 큰따옴표로도 여러 줄 문자열을 만들 수 있다.
let guestList = "손님:\n * John\n * Pete\n * Mary";
alert(guestList); // 손님 리스트를 여러 줄에 걸쳐 작성함
따옴표를 이용해 만든 여러줄 물자열과 백틱을 이용해 만든 여러 줄 문자열은 표현 방식만 다를 뿐 차이가 없다.
let str1 = "Hello\nWorld"; // '줄 바꿈 기호'를 사용해 두 줄짜리 문자열을 만듦
// 백틱과 일반적인 줄 바꿈 방법(엔터)을 사용해 두 줄짜리 문자열을 만듦
let str2 = `Hello
World`;
alert(str1 == str2); // true
자바스크립트에는 줄 바꿈 문자를 비롯한 다양한 `특수` 문자들이 있다.
유니코드 예시 :
alert( "\u00A9" ); // ©
alert( "\u{20331}" ); // 佫, 중국어(긴 유니코드)
alert( "\u{1F60D}" ); // 😍, 웃는 얼굴 기호(긴 유니코드)
모든 특수 문자는 이스케이프 문자(escape character)라고도 불리는 역슬래시 \ 로 시작한다.
역슬래시는 문자열 내에 따옴표를 넣을때도 사용할 수 있다.
alert( 'I\'m the Walrus!' ); // I'm the Walrus!
문자열의 길이
length 프로퍼티에는 문자열의 길이가 저장된다.
alert( `My\n`.length ); // 3
// \n은 ‘특수 문자’ 하나로 취급되기 때문에 My\n의 길이는 3이다.
특정 글자에 접근하기
문자열 내 특정위치(pos)에 접근하려면 [pos]같이 대괄호를 이용하거나 str.chrAt(pos)라는 메서드를 호출하면 된다.
let str = `Hello`;
// 첫 번째 글자
alert( str[0] ); // H
alert( str.charAt(0) ); // H
// 마지막 글자
alert( str[str.length - 1] ); // o
근래에는 대괄호를 이용하는 방식을 사용한다.(charAt은 하위 호환성을 위해 남아있는 메서드라고 생각)
두 접근 방식의 차이는 반환할 글자가 없을 때 []는 undefined를 charAt은 빈 문자열을 반환한다.
for ... of 를 사용하면 문자열을 구성하는 글자를 대상으로 반복 작업을 할 수 있다.
for (let char of "Hello") {
alert(char); // H,e,l,l,o (char는 순차적으로 H, e, l, l, o가 됩니다.)
}
문자열의 불변성
문자열은 수정할 수 없다. 따라서 문자열의 중간 글자 하나를 바꾸려고 하면 에러가 발생한다.
let str = 'Hi';
str[0] = 'h'; // Error: Cannot assign to read only property '0' of string 'Hi'
alert( str[0] ); // 동작하지 않습니다.
대,소문자 변경하기
toLowerCase() - 대문자를 소문자로 변경
toUpperCase() - 소문자를 대문자로 변경
글자 하나의 케이스만 변경하는 것도 가능하다.
alert( 'Interface'[0].toLowerCase() ); // 'i'
부분 문자열 찾기
str.indexOf
- 문자열 str의 pos에서부터 시작해 부분 문자열 substr이 어디에 위치하는지를 찾아준다.
부분 문자열을 찾으면 위치를 반환하고 그렇지 않으면 -1을 반환한다.
let str = 'Widget with id';
alert( str.indexOf('Widget') ); // 0, str은 'Widget'으로 시작함
alert( str.indexOf('widget') ); // -1, indexOf는 대·소문자를 따지므로 원하는 문자열을 찾지 못함
alert( str.indexOf("id") ); // 1, "id"는 첫 번째 위치에서 발견됨 (Widget에서 id)
str.indexOf(substr, pos)의 두 번째 매개변수 pos는 선택적으로 사용할 수 있는데 이를 명시하면 검색이 해당 위치부터 시작
let str = 'Widget with id';
alert( str.indexOf('id', 2) ) // 12
문자열 내 부분 문자열 전체를 대상으로 무언가를 하고 싶다면 반복문 안에 indexOf를 사용하면 된다.
반복문이 하나씩 돌때마다 검색 시작 위치가 갱신되면서 indexOf가 새롭게 호출된다.
let str = 'As sly as a fox, as strong as an ox';
let target = 'as'; // as를 찾아봅시다.
let pos = 0;
while (true) {
let foundPos = str.indexOf(target, pos);
if (foundPos == -1) break;
alert( `위치: ${foundPos}` );
pos = foundPos + 1; // 다음 위치를 기준으로 검색을 이어갑니다.
}
// =================================================================
// 짧게 줄이면
let str = "As sly as a fox, as strong as an ox";
let target = "as";
let pos = -1;
while ((pos = str.indexOf(target, pos + 1)) != -1) {
alert( `위치: ${pos}` );
}
# str.lastIndexOf(substr, position)
문자열 끝에서부터 부분 문자열을 찾는다는 점이 다르다.
반환되는 부분 문자열 위치는 문자열 끝이 기준
if 문의 조건식에 indexOf를 쓸 때 주의할 점이 있다.
let str = "Widget with id";
if (str.indexOf("Widget")) {
alert("찾았다!"); // 의도한 대로 동작하지 않습니다.
}
str.indexOf("Widget")은 0을 반환하는데 if문에서는 0을 false로 간주하므로 alert창이 뜨지 않는다.
따라서 부분 문자열 여부를 검사하려먼 -1과 비교해야 한다.
let str = "Widget with id";
if (str.indexOf("Widget") != -1) {
alert("찾았다!"); // 의도한 대로 동작합니다.
}
비트 NOT 연산자를 사용한 기법
비트 NOT연산자는 피연산자를 32비트 정수로 바꾼 후(소수부는 모두 버림) 모든 비트를 반전한다.
따라서 n이 32비트 정수일 때 ~n은 -(n+1)이 된다.
let str = "Widget";
if (~str.indexOf("Widget")) {
alert( '찾았다!' ); // 의도한 대로 동작합니다.
}
if (~str.indexOf(...)) 패턴의 코드를 만나면 '부분 문자열인지 확인’하는 코드라고 생각하면 된다.
includes, startsWith,endsWith
str.includes(substr,pos) 는 str에 부분 문자열 substr이 있는지에 따라 true,false를 반환한다.
부분문자열의 위치 정보는 필요하지 않고 포함 여부만 알고 싶을때 적합한 메서드
alert( "Widget with id".includes("Widget") ); // true
alert( "Hello".includes("Bye") ); // false
str.includes에도 str.indexOf처럼 두 번째 인수를 넘길시 해당 위치부터 문자열을 검색한다.
alert( "Widget".includes("id") ); // true
alert( "Widget".includes("id", 3) ); // false, 세 번째 위치 이후엔 "id"가 없습니다.
str.startsWith와 str.endsWith는 메서드 이름 그대로 문자열 str이 특정 문자열로 시작하는지(start with)여부와 특정 문자열로 끝나는지(end with) 여부를 확인할 때 사용할수 있다.
alert( "Widget".startsWith("Wid") ); // true, "Widget"은 "Wid"로 시작합니다.
alert( "Widget".endsWith("get") ); // true, "Widget"은 "get"으로 끝납니다.
부분 문자열 추출하기
세가지 메서드를 사용 substring, substr,slice
str.slice(start [, end])
- 문자열의 start부터 end까지(end는 미포함)을 반환한다.
let str = "stringify";
alert( str.slice(0, 5) ); // 'strin', 0번째부터 5번째 위치까지(5번째 위치의 글자는 포함하지 않음)
alert( str.slice(0, 1) ); // 's', 0번째부터 1번째 위치까지(1번째 위치의 자는 포함하지 않음)
두 번째 인수가 생략된 경우에는 명시한 위치부터 문자열 끝까지를 반환한다.
let str = "stringify";
alert( str.slice(2) ); // ringify, 2번째부터 끝까지
start와 end는 음수가 될수도 있다. 음수를 넘기면 문자열 끝에서부터 카운팅을 시작
let str = "stringify";
// 끝에서 4번째부터 시작해 끝에서 1번째 위치까지
alert( str.slice(-4, -1) ); // gif
str.substring(start [, end])
- start와 end 사이에 있는 문자열을 반환
substring은 slice와 아주 유사하지만 start가 end보다 커도 문제가 없다.
let str = "stringify";
// 동일한 부분 문자열을 반환합니다.
alert( str.substring(2, 6) ); // "ring"
alert( str.substring(6, 2) ); // "ring"
// slice를 사용하면 결과가 다릅니다.
alert( str.slice(2, 6) ); // "ring" (같음)
alert( str.slice(6, 2) ); // "" (빈 문자열)
substring은 음수 인수를 허용하지 않는다 (음수는 0으로 처리)
str.substr(start [,length]);
- start에서부터 시작해 length개의 글자를 반환한다
substr은 끝 위치 대신에 길이를 기준으로 문자열을 추출한다는 점에서 substring과 slice와 차이가 있다.
let str = "stringify";
alert( str.substr(2, 4) ); // ring, 두 번째부터 글자 네 개
첫 번째 인수가 음수이면 뒤에서부터 개수를 센다.
let str = "stringify";
alert( str.substr(-4, 2) ); // gi, 끝에서 네 번째 위치부터 글자 두 개
# substr은 브라우저 이외의 호스트 환경에서는 제대로 동작하지 않을 수 있다.
slice는 음수 인수를 허용한다는 측면에서 substring보다 조금 더 유연하다
# 문자열에 쓸 수 있는 유용한 메서드
str.trim() – 문자열 앞과 끝의 공백 문자를 제거한다.
str.repeat(n) – 문자열을 n번 반복합니다.
문자열 비교하기
문자열을 비교할 땐 알파벳 순서를 기준으로 글자끼리 비교가 이루어 진다.
하지만 몇가지 이상한 것들이 있다.
1. 소문자는 대문자보다 항상 크다.
alert( 'a' > 'Z' ); // true
2. 발음 구별 기호가 붙은 문자는 알파벳 순서 기준을 따르지 않는다.
alert( 'Österreich' > 'Zealand' ); // true
모든 문자열은 UTF-16을 사용해 인코딩된다.
UTF-16에서는 모든 글자가 숫자 형식의 코드와 매칭
str.codePointAt(pos) -> 코드로 글자를 얻거나 글자에서 연관 코드를 알아낼 수 있는 메서드
pos에 위치한 글자의 코드를 반환
// 글자는 같지만 케이스는 다르므로 반환되는 코드가 다릅니다.
alert( "z".codePointAt(0) ); // 122
alert( "Z".codePointAt(0) ); // 90
String.fromCodePoint(code)
숫자 형식의 code에 대응하는 글자를 만들어 준다.
alert( String.fromCodePoint(90) ); // Z
문자열 제대로 비교하기
언어마다 문자 체계가 다르기 때문에 문자열을 비교하려면 페이지에서 어떤 언어를 사용하고 있는지 브라우저가 알아야한다.
모던 브라우저 대부분이 국제화 관련 표준 ECMA-402를 지원 (IE10은 Intl.js라이브러리 사용)
ECMA-402에는 언어가 다를 때 적용할 수 있는 문자열 비교 규칙과 이를 준수하는 메서드가 정의되어 있다.
str.localeCompare(str2)를 호출하면 ECMA-402에서 정의한 규칙에 따라 str이 str2보다 작은지,같은지,큰지를 나타내주는 정수가 반환단다.
str 이 str2보다 작으면 음수를 반환
str 이 str2보다 크면 양수를 반환
str 이 str2과 같으면 0을 반환
'자바 스크립트' 카테고리의 다른 글
자바스크립트 iterable (0) | 2020.12.14 |
---|---|
자바스크립트 배열 (0) | 2020.12.13 |
자바스크립트 숫자형 (0) | 2020.12.11 |
자바스크립트 원시값의 메서드 (1) | 2020.12.08 |
자바 스크립트 심볼형 (0) | 2020.12.08 |
댓글