[JS] String

Yunhye Park·2023년 10월 3일

지식 습득

목록 보기
4/11
post-thumbnail

코딩온에서 제공한 자바스크립트 온라인 수업에서 형변환 파트가 있었다. 문자열로 변경할 땐 String 혹은 toString을 사용할 수 있다는 언급을 보고, String을 정리해보고 싶어졌다. 포스팅의 대부분은 책 '자바스크립트 Deep Dive'를 참고했다.


우선 자바스크립트의 데이터타입은 기본형(primitive type)과 참조형(reference type)으로 나뉜다. 기본형 7가지 중 하나가 문자열이다. 즉 문자열은 원시값이 존재한다. 그런데 String 객체를 생성하는 표준 빌트인 생성자 함수는 왜 존재할까?

🔍 표준 빌트인 객체
자바스크립트엔 약 40여개의 표준 빌트인 객체가 있다. String도 그중 하나다. Math, Reflect, JSON을 제외하고는 인스턴스를 생성할 수 있는 생성자 함수 객체라서 프로토타입 메서드(ex. Object.prototype.toString)와 정적 메서드를 제공하고, 생성자 함수 객체가 아닌 표준 빌트인 객체는 정적 메서드만 제공한다.
참고 문서 : 표준 빌트인 객체

문자열 원시값의 래퍼 객체

질문에 대한 답은 아래 예제를 살펴보면 알 수 있다.

const str = 'hello';

console.log(str.length); // 5
console.log(str.toUpperCase()); // HELLO

문자열을 마침표 표기법 또는 대괄호 표기법으로 접근할 수 있다. 마치 참조형인 객체처럼 작동하는 것이다. 자바스크립트 엔진이 일시적으로 원시값을 연관된 객체로 변환해 주어서 가능한 일이다. 이렇게 생성되는 임시 객체가 래퍼 객체(wrapper object)이다.

원시값을 객체처럼 사용하면 자바스크립트 엔진이 암묵적으로 연관 객체를 생성하고, 그렇게 생성된 객체의 프로퍼티에 접근하거나 메서드를 호출하고 나면 다시 원시값으로 되돌린다.

문자열을 객체처럼 쓸 수 있어도 원본(문자열)은 원시 값이고, 원시 값은 변경 불가능하다. 따라서 String 래퍼 객체는 직접 원본 객체를 변경하지 못하고, 새로운 문자열을 반환하는 읽기 전용 객체이다.

위의 예시를 주석과 함께 다시 보자.

// 변수 str에 문자열 'hello'를 담는다
const str = 'hello';

// 마침표 표기법으로 접근하자,
// 문자열의 래퍼 객체인 String 생성자 함수의 인스턴스(객체)로 변환된다.
console.log(str.length); // 5
console.log(toUpperCase()); // HELLO

//래퍼 객체로 프로퍼티 접근이나 함수 호출이 끝나자 원시값으로 되돌린다.
console.log(typeof str); // string

문자열이 원시값으로 돌아가면, 래퍼 객체는 아무도 참조하지 않아서 가비지 컬렉션 대상이다. 객체처럼 프로퍼티를 동적 추가했을 때(ex. str.name = 'Kate';)도 마찬가지다. 래퍼 객체는 함수 호출이나 프로퍼티 접근이 끝나자마자 가비지 컬렉션이 된다.

해당 래퍼 객체의 프로퍼티를 출력하려고 해도 가비지 컬렉션이 된 것을 불러올 수 없으니, 결국 새롭게 암묵적으로 생성된 래퍼 객체의 프로퍼티를 가리키다 보니 undefined를 반환한다.

앞서 언급했듯 숫자와 불리언 값도 똑같이 작동하지만, null과 undefined는 래퍼 객체를 생성하지 않아 객체처럼 접근 시 에러가 발생한다.

cf)
ES6에서 추가된 원시값, '심벌(symbol)'은 다르게 작동한다.

String 생성자 함수

표준 빌트인 객체인 String은 생성자 함수 객체다.

new 연산자와 함께 함수 호출

new 연산자와 함께 호출하면 [[stringData]] 내부 슬롯에 빈 문자열을 할당한 String 래퍼 객체를 생성한다.

// 인수 없이 생성
const strObj = new String();
console.log(strObj);

/* String {''}
* length: 0
* [[Prototype]]: String 
* [[PrimitiveValue]]: ""
*/

// 인수로 문자열을 넣어 생성
const strObj2 = new String('Kate');
console.log(strObj2);
/* String {'Kate'}
* 0: "K"
* 1: "a"
* 2: "t"
* 3: "e"
* length: 4
* [[Prototype]]: String
* [[PrimitiveValue]]: "Kate"
*/

아래의 경우엔 에러가 발생하지 않는다.

  1. 문자열이 아닌 인수로(ex. 455, null) 값을 전달.
    암묵적으로 인수가 문자열로 강제 변환되어 똑같이 String 래퍼 객체를 생성한다.

  2. 인덱스를 사용하여 프로퍼티 변경 시도.
    원시값은 변경할 수 없으니 변경 되지 않지만 에러가 발생하진 않는다.

new 연산자 없이 함수 호출

명시적 타입 변환을 할 때 사용한다.

String(433); // '433'
String(null); // 'null'
String(true); // 'true'

숫자는 물론 불리언 값이나 null 또한 형변환 시킨다.

이와 비슷하게 문자열로 변환하는 toString 메서드는 null과 undefined를 인수로 받을 시, 에러가 발생한다.

null.toString();

toString null 오류


참고

도서 자바스크립트 Deep Dive

profile
일단 해보는 편

0개의 댓글