<aside> <img src="/icons/chat_gray.svg" alt="/icons/chat_gray.svg" width="40px" /> ECMAScript 명세서 6.1.4에서 명시한 바와 같이 자바스크립트에서는 문자열을 UTF-16 인코딩 코드 포인트의 시퀀스로 해석한다.

</aside>

32.1 String 생성자 함수

표준 빌트인 객체인 String 객체인 생성자 함수 객체이므로 new 연산자와 함께 호출하여 String 인스턴스를 생성할 수 있다.

String 생성자 함수에 인수를 전달하지 않고 new 연산자와 함께 호출하면 [[StringData]] 내부 슬롯에 빈 문자열을 할당한 String 래퍼 객체를 생성한다.

const strObj = new String();
console.log(strObj);
// String {length: 0, [[[PrimitiveValue]]](<https://hardy716.notion.site/32-String-fbe908db56694012819ce32fc5ac2369>): ""}

String 생성자 함수에 인수로 문자열을 전달하면서 new 연산자와 함께 호출하면 [[StringData]] 내부 슬롯에 인수로 전달받은 문자열을 할당한 String 래퍼 객체를 생성한다.

const strObj = new String('Aa');
console.log(strObj);
// String {0: "A", 1: "a", length: 2, [[[PrimitiveValue]]](<https://hardy716.notion.site/32-String-fbe908db56694012819ce32fc5ac2369>): "Aa"}

String 생성자 함수에 인수로 문자열이 아닌 값을 전달하면서 new 연산자와 함께 호출하면 [[StringData]] 내부 슬롯에 인수를 문자열로 강제 변환 후 할당하여 String 래퍼 객체를 생성한다.

const strObj = new String(null);
console.log(strObj);
// String {0: "n", 1: "u", 2: "l", 3: "l", length: 4, [[[PrimitiveValue]]](<https://hardy716.notion.site/32-String-fbe908db56694012819ce32fc5ac2369>): "null"}

[[PrimitiveValue]]는 접근 불가능한 프로퍼티이며, [[StringData]] 내부 슬롯을 가리킨다. ES5에서는 [[StringData]] 자체를 [[PrimitiveValue]]라고 불렀다.

11.1.2절 “문자열과 불변성”에서 살펴보았듯이 String 래퍼 객체는 인덱스를 나타내는 숫자 형식의 문자열을 프로퍼티 키로, 각 문자를 프로퍼티 값으로 갖는 유사 배열 객체이면서 이터러블이다.

따라서 String 래퍼 객체는 배열과 유사하게 인덱스를 사용하여 각 문자에 접근할 수 있다.

단, 문자열은 원시 값이므로 변경할 수 없다는 것에 주의해야 한다. 이때 에러는 발생하지 않는다.

9.3절 “명시적 타입 변환”에서 살펴보았듯이 new 연산자를 사용하지 않고 String 생성자 함수를 호출하면 String 인스턴스가 아닌 문자열을 반환한다. 이를 이용하여 명시적으로 타입을 변환하기도 한다.

32.2 length 프로퍼티

length 프로퍼티는 문자열의 문자 개수를 반환한다.

console.log(''.length);  // 0

32.3 String 메서드

String 객체에는 배열과 다르게 원본 String 래퍼 객체를 직접 변경하는 mutator 메서드는 존재하지 않는다.

문자열은 변경 불가능한 원시 값이기 때문에 String 래퍼 객체도 읽기 전용(read-only) 객체로 제공된다.

따라서 String 객체의 모든 메서드는 String 래퍼 객체를 직접 변경할 수 없고, String 객체의 메서드는 언제나 새로운 문자열을 생성하여 반환한다.

String methods are intentionally generic; it does not require that its this value be a String object. Therefore, it can be transferred to other kinds of objects for use as a method.

ECMAScript (ECMA-262) Living Standard

32.3.1 String.prototype.indexOf

indexOf 메서드는 호출한 String 객체에서 인수로 전달받은 문자열과 일치하는 첫 번째 인덱스를 반환한다.

이때 대소문자를 구분하며, indexOf 메서드의 2번째 인수로 검색을 시작할 인덱스를 전달할 수 있다.

str.indexOf(searchString[, position])

indexOf 메서드의 2번째 인수 position는 어떤 정수값이라도 가능하다.

var str = 'Modern JavaScript Deep Dive.';
var count = 0;
var pos = str.indexOf('De');

while (pos !== -1) {
  count++;
  pos = str.indexOf('De', pos + 1); // 첫 번째 De 이후의 인덱스부터 e를 찾습니다.
}

console.log(count);  // 1

만약 검색에 실패하면 -1을 반환한다. 이때 ‘0’을 평가했을 때 true가 아니고, -1을 평가했을 때 false가 아닌 것에 주의해야 한다. 임의의 문자열에 특정 문자열이 있는지를 확인하는 올바른 방법은 아래와 같다.

'(임의의 문자열)'.indexOf('(특정 문자열)') !== -1;

만약 인수로 아무 값도 주어지지 않으면 ToString(ECMAScript 명세서 7.1.17-3)에 의해 암묵적으로 문자열 “undefined”로 변환된다.

32.3.2 String.prototype.search

search 메서드는 String 객체에서 인수로 전달받은 정규 표현식과 매치하는 문자열의 인덱스를 반환한다.

str.search(regexp)

const paragraph = 'Modern JavaScript Deep Dive.';

// any character that is not a word character or whitespace
const regex = /[^\\w\\s]/g;

console.log(paragraph.search(regex));  // 27

console.log(paragraph[paragraph.search(regex)]);  // .

만약 검색에 실패하면 -1을 반환한다. 이때 ‘0’을 평가했을 때 true가 아니고, -1을 평가했을 때 false가 아닌 것에 주의해야 한다. 임의의 문자열에 특정 문자열이 있는지를 확인하는 올바른 방법은 아래와 같다.

'(임의의 문자열)'.search((정규 표현식)) !== -1;

그러나 위의 방법보다는 RegExp 프로토타입의 test 메서드를 사용하는 것을 권장한다.

더 많은 정보를 원한다면 match() 메서드를 사용하는 것을 권장한다.

만약 인수로 non-RegExp 객체가 전달되면, new RegExp(obj)에 의해 RegExp로 암묵적으로 변환된다.

32.3.3 String.prototype.includes

ES6에서 도입된 includes 메서드는 하나의 문자열이 String 객체에서 포함되어 있는지를 판별하고, boolean 값을 결과로 반환한다.

이때 대소문자를 구분하며, includes 메서드의 2번째 인수로 검색을 시작할 인덱스를 전달할 수 있다.

str.includes(searchString[, position])

includes 메서드의 2번째 인수 position는 어떤 정수값이라도 가능하다.

indexOf 메서드의 2번째 인수와 거의 유사하게 동작하지만 str.length보다 크거나 같은 경우 -1이 아니라 false를 반환한다는 점이 다르다(boolean 값을 결과로 반환하는 메서드이기 때문).

const sentence = 'Modern JavaScript Deep Dive.';

const word = 'De';

console.log(`The word "${word}" ${sentence.includes(word) ? 'is' : 'is not'} in the sentence.`);
// "The word "De" is in the sentence."