Juni_Dev_log

모던 자바스크립트 입문(MJB) [5장] 표현식과 연산자 - ③ 문자열 제어하기 본문

Theorem (정리)/Javascript

모던 자바스크립트 입문(MJB) [5장] 표현식과 연산자 - ③ 문자열 제어하기

Juni_K 2020. 11. 13. 16:14

① 문자열 연결

+ 연산자는 피연산자가 모두 문자열이면 문자열로 연결한다.

"Hello" + "World!" // "Hello World!"

"1" + "2" // "12"

피연산자 중 하나가 문자열 또는 문자열로 변환될 수 있는 객체라면 다른 피연산자의 타입을 문자열로 바꾼 다음 연결한다.

10 + "little indians" // "10 little indians"

1 + {} // "1[object Object]"

true + (new Date()) // "trueFri Nov 13 2020 14:01:17 GMT+0900 (대한민국 표준시)"

그렇지 않으면 피연산자 두 개를 숫자 또는 NaN으로 타입을 바꾸어 더한다.

단, 이 경우는 자바스크립트의 실행 환경에 따라 처리하는 방법이 다르다.

var a = 3;
console.log("a 값은" + a + "입니다."); // a값은 3 입니다.

② 문자열을 조작하는 메서드

문자열을 처리하기 위한 객체로 String 객체가 마련되어 있다.

문자열을 String 객체로 변환하려면 String 생성자를 이용한다.

var msgObj = new String("Everything is practice.");

이처럼 원시 값을 객체로 변환하는 행위를 가리켜 원시 값을 객체로 래핑(wrapping) 한다고 한다.

String 객체에는 문자열을 처리하기 위한 다양한 프로퍼티와 메서드가 마련되어 있다.

(String 객체의 주요 메서드)

메서드 설명 예제
codePointAt(n) 대상 문자열 n번째 문자의 코드 포인트의 스칼라 값을 10진수로 표현한 값  msgObj.codePointAt(3)
// 114
charAt(n) 대상 문자열의 n번째 문자 msgObj.charAt(3)
//"r"
charCodeAt(n) 대상 문자열 n번쨰 문자의 UTF-16코드를 10진수로 표기한 값 msgObj.charCodeAt(3)
// 114
concat([s1, s2, ...]) 대상 문자열과 인수의 문자열을 연결해서 반환 msgObj.concat(["hi","test"])
// "Everything is practice.hi,test"
endsWith(s [, n]) 대상 문자열의 n번째 문자부터 문자열 s로 끝나는지를 판별한 논리값.
n을 생략하면 문자열의 끝부터 검색한다.
msgObj.endsWith("s")
// false
msgObj.endsWith(".")
// true
includes(s [, n]) 대상 문자열의 n번째 문자부터 문자열 s를 포함하는지 판별한 논리값.
n을 생략하면 문자열의 끝부터 검색한다.
msgObj.includes("s")
// true
msgObj.includes("z")
// false
indexOf(s) 대상 문자열에서 s가 처음 나오는 위치 msgObj.indexOf("e")
// 2
lastIndexOf(s) 대상 문자열에서 s가 마지막으로 나오는 위치 msgObj.lastIndexOf("e")
// 21
localeCompare(s) 대상 문자열이 문자의 정렬 순서에 따라 s의 앞뒤에 있는지 또는 같은 위치에 있는지 표시 msgObj.localeCompare("e")
// 1
match(r) 대상 문자열에 정규 표현식 r을 매칭한 매칭값  
normalize(form) form이 제시한 방식으로 유니코드 문자를 정규화  
repeat(n) 대상 문자열을 n개 연결한 문자열 msgObj.repeat(3)
// "Everything is practice.Everything is practice.Everything is practice."
replace(s1, s2) 대상 문자열에 포함된 문자열 s1을 문자열 s2로 치환한 결괏값 msgObj.replace("e","z")
// "Evzrything is practice."
search(r) 대상 문자열에서 정규식 r이 일치한 위치의 인덱스 값  
slice(m, n) 대상 문자열의 m번째 이후 n번째 미만의 부분 문자열을 반환.
m과 n이 음수이면 문자열 끝이 시작 위치가 된다.
msgObj.slice(2,5)
// "ery"
split(s [,n]) 대상 문자열을 문자열 s로 분할한 문자열 배열을 반환.
n은 발견된 문자열의 개수를 제한.
msgObj.split("e")
// ["Ev", "rything is practic", "."]
startsWith(s [,n]) 대상 문자열의 n번째 문자부터 문자열 s로 시작하는지를 판별한 논리값.
n이 발견된 문자열의 개수를 제한.
msgObj.startsWith("E")
//true
msgObj.startsWith("e")
//false
substring(m, n) 대상 문자열의 m번째 이후 n번째 미만의 부분 문자열을 반환. msgObj.substring(2,5)
// "ery"
toLocaleLowerCase() 대상 문자열을 로케일(언어)에 맞는 소문자로 변환.  
toLocaleUpperCase() 대상 문자열을 로케일(언어)에 맞는 대문자로 변환.  
toLowerCase() 대상 문자열을 소문자로 변환. msgObj.toLowerCase()
// "everything is practice."
toString() String 객체를 문자열 값으로 변환. msgObj.toString()
// "Everything is practice."
toUpperCase() 대상 문자열을 대문자로 변환. msgObj.toUpperCase()
// "EVERYTHING IS PRACTICE."
trim() 앞뒤 공백을 제거. msgObj.trim()
// "Everything is practice."
valueOf() String 객체를 문자열 값으로 변환 msgObj.valueOf()
// "Everything is practice."

문자열의 길이는 배열과 마찬가지로 length 프로퍼티로 구할 수 있다.

msgObj.length // 23

이 때 String 객체로 표시되는 문자열의 각 문자에는 왼쪽부터 순서대로 0부터 시작되는 번호가 매겨져있다.

0번째 문자는 "E" 고, 끝에서 3번째 문자는 "c"가 되는 것이다.

 

chatAt 메서드를 이용하면 문자열의 n번째 문자를 쉽게 구할 수 있다.

msgObj.charAt(3) // "r" 

이러한 문자열 객체의 프로퍼티와 메서드는 문자열에서도 이용할 수 있다.

var msg = "Everything is practice."
console.log(msg.length); // 23
console.log(msg.charAt(3)); // r

문자열은 객체가 아니므로 프로퍼티를 가지고 있지 않다.

그런데 이것은 어떻게 동작하는걸까? 문자열에서 프로퍼티를 사용하려고 하면, 문자열이 자동으로 String 객체로 변환되기 때문이다.

var c = msg.charAt(3);

var msgObj = new String(msg);
// 문자열을 String 객체로 변환

var c = msgObj.charAt(3); 
// String 객체의 메서드를 사용

실제로 msgObj 가 실행되는 순간에 일시적으로 생성되는 String 객체이므로, 사용자에게는 보이지 않는다.

처리가 끝나면 곧바로 메모리에서 삭제된다. 이러한 객체를 래퍼 객체 라고 한다.

자바스크립트에서는 원시값을 처리할 때, 래퍼 객체로 자동 변환하고 래퍼 객체의 기능을 활용해서 다양한 작업을 수행한다.

문자열 -> String 객체
숫자 -> Number 객체
논리값 -> Boolean 객체
null, undefined -> 래퍼 객체 없음

원시 값을 처리할 때는 대부분 msg.charAt(3) 처럼 원시 값의 메서드를 바로 호출하며, String 객체 등으로 다시 변환해서 처리하지는 않는다.

왜냐하면 String 객체는 원시 값이 아니라 객체기 때문에 원시 값이 들어올 것으로 가정하고 작성한 코드에 String 객체를 섞어서 사용하면 오류가 발생할 수 있기 때문이다.

var msg = "Everything is practice.";
console.log(msg); // Everything is practice.

다음과 같이 msg 를 String 객체로 변환하면 의도한 것과 다른 결과가 나온다.

var msg = new String("Everything is practice.");
console.log(msg); // String [[PrimitiveValue]]: "Everything is practice."

이 코드를 문자열을 출력하도록 수정하려면 다음과 같이 valueOf() 메서드를 사용해서 String 객체를 문자열로 다시 한 번 변환해야한다.

var msg = new String("Everything is practice.").valueOf();
console.log(msg); // Everything is practice.

자바스크립트의 문자열은 불변이라는 것을 기억하라.

replace와 toUpperCase 메서드 등 새로운 문자열을 반환하며 메서드를 호출한 문자열을 수정되지 않는다.

 

③ String 생성자의 메서드

자바스크립트의 함수는 객체이며 프로퍼티를 가지고 있다.

String 생성자 또한 일종의 함수이며 프로퍼티를 가지고 있다.

프로퍼티 설명 비고
String.length 항상 1  
String.formCharCode() 인수로 넘긴 문자 코드 목록으로 문자열을 만들어 반환  
 String.formCodePoint() 인수로 넘긴 코드 포인트 목록으로 문자열을 만들어 반환  
String.prototype String의 프로토타입 객체  
String.raw() 템플릿 문자열의 원시 문자열 형식을 반환  

String.formCharCode 메서드는 문자 코드를 문자열로 반환한다.

쉼표로 구분한 문자코드 여러개를 인수로 넘기면 각 문자 코드가 뜻하는 문자를 문자열로 연결해서 반환한다.

String.fromCharCode(65,66,67)
// "ABC"

이를 이용해서 써로게이트 페어 문자를 구하려면 쉼표로 구분한 써로게이트 페어를 인수로 넘긴다.

String.fromCharCode(0xd83d, 0xdcd6)
// "📖"

String.fromCharCode 는 써로게이트 페어의 다섯 자릿수 코드 포인트 표현은 지원하지 않으며, 실제로 써로게이트 페어의 다섯자릿수 코드 포인트를 받으면 예기치 않은 동작을 한다.

String.fromCharCode(0x1f4d6)
// ""

ES6부터 추가된 String.fromCharCode 메서드는 UTF-16 부호 값과 유니코드 포인트 스칼라 값을 모두 지원한다.

따라서, 써로게이트 페어의 코드 포인트 스칼라 값을 인수로 넘겨도 올바른 값을 반환한다.

 

또한 유니코드 리터럴을 사용하는 방법도 있다.

"\u{1f4d6}"
// "📖"

④ 문자열을 배열로 읽고 쓰기

문자열을 읽을 때는 charAt 메서드 대신 대괄호 연산자를 사용할 수 있다.

var msg = "Everything is practice."
msg[3]
// "r"

msg[msg.length-1]
// "."

그러나 배열처럼 값에 대입해서 수정할 수는 없다. 대입해도 무시된다.

msg[3] = "R";
console.log(msg); 
// Everything is practice.

그리고 써로게이트 페어로 표현하는 문자는 두 개의 배열 요소로 분리한다.

var s = "📖";
s.codePointAt(0).toString(16) // "1f4d6" : 코드 포인트의 스칼라 값
s[0].codePointAt(0).toString(16) // "d83d" : 상위 써로게이트
s[1].codePointAt(0).toString(16) // "dcd6" : 하위 써로게이트
s[0] + s[1] // "📖"
▶ 써로게이트 페어란?

유니코드는 문자 집합과 문자 인코딩 방식을 정한 표준 문자 코드이며 유니코드 문자 집합에는 전 세계에서 사용하는 문자가 포함되어 있다. 유니코드 문자 집합에서 각 문자의 위치를 코드 포인트라고 부르며, 코드 포인트에는 스칼라 값이라는 숫자가 할당되어 있다.
스칼라 값은 코드 포인트 값이라고도 부르며, U+8A9E 처럼 앞에 U+를 붙인 16진수로 표현한다.
이러한 유니코드의 인코딩 방식에는 UTF-8, UTF-16, UTF-32 등이 있다.

2바이트의 인코딩 값을 한 쌍(a ,b)로 묶은 것을 가리켜 써로게이트 페어라고 부른다.
이 때 a는 상위 써로게이트 / b는 하위 써로게이트 라고 부른다.
// 써로게이트가 포함된 문자열을 배열로 만들기
function stringToArray(s) {
	return s.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]:[^\uD800-\uDFFF]/g) :: [];
}
stringToArray("📖 모던 자바스크립트 입문");

 

Comments