위 코드를 개발자 도구에서 실행해보면 [[PrimitiveValue]] 라는 접근할 수 없는 프로퍼티가 보인다. 이는 [[StringData]] 내부 슬롯을 가리킨다. ES5에서는 [[StringData]]를 [[Primitive Value]]라 불렀다.
String 생성자 함수의 인수로 문자열을 전달하면서 new 연산자와 함께 호출하면 [[StringData]] 내부 슬롯에 인수로 전달받은 문자열을 할당한 String 래퍼 객체를 생성한다.
const strObj = new String('Lee');
console.log(strObj);
// [String: 'Lee']
String 래퍼 객체는 배열과 마찬가지로 length 프로퍼티와 인덱스를 나타내는 숫자 형식의 문자열을 프로퍼티 키로, 유사 배열 객체이면서 이터러블이다.
console.log(strObj[0]); // L
단 문자열은 원시 값이므로 변경할 수 없다.
String 생성자함수의 인수로 문자열이 아닌 인수를 전달하면 강제 변환한 후, [[StringData]]에 변환된 문자열을 할당한 String 래퍼 객체를 생성한다
new 연산자를 사용하지 않고 String 생성자 함수를 호출하면 String 인스턴스가 아닌 문자열을 반환한다. ⇒ 명시적 타입 변환
2 length 프로퍼티
'Hello'.length; // => 5
'안녕하세요!'.length; // => 6
String 래퍼 객체는 배열과 마찬지인 유사배열, 즉 length 프로퍼티와 인덱스를 나타내는 숫자를 프로퍼티 키로, 각 문자를 프로퍼티 값으로 가지므로 String 래퍼 객체는 유사 배열 객체다.
인덱스 번호로 해당 문자열이 아닌 문자에 접근 가능하다.
3 String 메소드
String 메소드는 String 타입 자체가 원시 타입 즉 변경이 불가능한 원시 값이기 때문에 String 래퍼 객체도 읽기 전용(read-only) 객체로 제공된다.
3.1 String.prototype.indexOf
대상 문자열(메소드를 호출한 문자열)에서 인수로 전달받은 문자열을 검색하여 첫 번째 인덱스를 반환한다. 실패하면 -1을 반환한다.
const str = 'Hello World';
// 문자열 str에서 'l'을 검색하여 첫 번째 인덱스를 반환한다.
str.indexOf('l'); // => 2
// 문자열 str에서 'or'을 검색하여 첫 번째 인덱스를 반환한다.
str.indexOf('or'); // => 7
// 문자열 str에서 'x'을 검색하여 첫 번째 인덱스를 반환한다.
str.indexOf('x'); // => 3
// 문자열 str의 인덱스 3부터 'l'을 검색하여 첫 번째 인덱스를 반환한다.
str.indexOf('l', 3); // -> 3
if(str.indexOf('Hello') !== -1){
// 문자열 str에 'Hello'가 들어있는 경우 처리할 내용
}
// ES6에 서 도입된 String.prototype.includes 메소드를 사용하면 가독성이 더 좋다.
if(str.includes('Hello')){
// 문자열 str에 'Hello'가 들어있는 경우 처리할 내용
}
3.2 String.prototype.search
대상 문자열에서 인수로 전달받은 정규 표현식과 매치하는 문자열을 검색하여 일치하는 문자열의 인덱스를 반환한다.
substring의 메소드의 두번째 인수를 생략한 경우 첫 번째 인수로 전달한 인덱스에 위치하는 문자 부분부터 마지막 문자까지 부분 문자열을 반환한다.
const str = "Hello world";
// 인덱스 1번부터 마지막 문자까지 부분 문자열을 반환한다.
console.log(str.substring(1)); // ello world
substring 메소드의 첫 번째 인수는 두 번째 인수보다 작은 정수이어야 정상이다 하지만 다음과 같은 경우에서도 작동이 된다.
첫 번째 인수 > 두 번째 인수인 경우 두 인수는 교환이 된다.
인수 < 0 또는 NaN일 경우 0으로 취급이 된다.
인수 > 문자열의 길이(str.length)인 경우 인수는 문자열의 길이 (str.length)로 취급된다.
const str = "Hello world";
// 첫 번째 인수 > 두번째 인수인 경우 두 인수는 교환된다.
console.log(str.substring(4, 1)); // ell
// 인수 < 0 또는 NaN인 경우 0으로 취급된다.
console.log(str.substring(-2)); // Hello world
// 인수 > 문자열의 길이(str.length)인 경우 인수는 문자열의 길이(str.length)로 취급된다.
console.log(str.substring(1, 100)); // ello world
console.log(str.substring(20)); // ''
String.prototype.indexOf 메소드와 함께 사용하면 특정 문자열을 기준으로 앞뒤에 위치한 부분 문자열을 취득할 수 있다.
const str = "Hello world";
// 스페이스를 기준으로 앞에 있는 부분 문자열 취득
console.log(str.substring(0, str.indexOf(" "))); // Hello
// 스페이스를 기준으로 뒤에 있는 부분 문자열 취득
console.log(str.substring(str.indexOf(" ") + 1, str.length)); // world
3.8 String.prototype.slice
substring 메소드와 동일하게 동작한다 단, slice 메소드에는 음수인 인수를 전달할 수 있다. 음수인 인수를 전달하면 대상 문자열의 가장 뒤에서부터 시작하여 문자열을 잘라내어 반환한다.
const str = "hello world";
// substring과 slice 메소드는 동일하게 동작한다.
// 0번째부터 5번째 이전 문자까지 잘라내어 반환
console.log(str.substring(0, 5)); // hello world
console.log(str.slice(0, 5)); // hello world
// 인덱스가 2인 문자부터 마지막 문자까지 잘라내어 반환
console.log(str.substring(2)); // llo world
console.log(str.slice(2)); // llo world
// 인수 < 0 또는 NaN인 경우 0으로 취급된다.
console.log(str.substring(-5)); // hello world
// slice 메소드는 음수인 인수를 전달할 수 있다. 뒤에서 5자리를 잘라내어 반환한다.
console.log(str.slice(-5)); // world
3.9 String.prototype.toUppperCase
대상 문자열을 모두 대문자로 변경한 문자열을 반환한다.
const str = "Hello world";
console.log(str.toUpperCase()); // HELLO WORLD
3.10 String.prototype.toLowerCase
대상 문자열을 모두 소문자로 변경한 문자열을 반환한다.
const str = "Hello world";
console.log(str.toLowerCase()); // hello world
3.11 String.prototype.trim
trim 메소드는 대상 문자열 앞뒤에 공백 문자가 있을 경우 이를 제거한 문자열을 반환한다.