CH 32. String
32.1 String 생성자 함수
- 각 문자를 프로퍼티 값으로 갖는 유사 배열 객체이면서 이터러블
- 문자열은 원시 값이므로 변경 불가, 이때 에러는 발생하지 않음
- 생성자 함수의 인수로 문자열이 아닌 값을 전달하면 인수를 문자열로 강제 변환 후 객체 생성함
const strObj = new String('Lee');
strObj[0] = 'S';
console.log(strObj); // 'Lee'
let strObj = new String(123);
console.log(strObj);
// String {0:"1", 1:"2", 2:"3", length:3, [[PrimitiveValue]]:"123"}
strObj = new String(null);
console.log(strObj);
//String {0:"n", 1:"u", 2:"l", :"l", length:4, [[PrimitiveValue]]:"null"}
- new 연산자 사용하지 않고 String 생성자 함수를 호출하면 String 인스턴스가 아닌 문자열을 반환함
// 숫자 -> 문자열
String(1); // "1"
Stirng(NaN); // "NaN"
String(Infinity); // "Infinity"
// 불리언 -> 문자열
String(true); // "true"
32.2 length 프로퍼티
- 문자열의 개수 반환
'Hello'.length; // 5
'안녕하세요!'.length; // 6
32.3 String 메서드
- String 객체에는 원본 래퍼 객체를 직접 변경하는 메서드는 존재하지 않음
- 즉, String 메서드는 언제나 새로운 문자열을 반환함
- 문자열은 변경 불가능한 원시 값 -> String 래퍼 객체도 읽기 전용 객체로 제공됨
32.3.1 String.prototype.indexOf
- 메서드를 호출한 문자열에서 인수로 전달받은 문자열을 검색해 첫 번째 인덱스 반환
- 검색에 실패하면 -1을 반환
- 특정 문자열이 존재하는지 확인할 때 유용함
const str = 'Hello World';
str.indexOf('l'); // 2
str.indexOf('or'); // 7
str.indexOf('x'); // -1
// 문자열 str의 인덱스 3부터 'l'을 검색해 첫 번째 인덱스를 반환함
str.indexOf('l', 3); // 3
32.3.2 String.prototype.search
- 인수로 전달받은 정규 표현식과 매치하는 문자열을 검색하여 일치하는 문자열의 인덱스를 반환함
- 검색에 실패하면 -1 반환
const str = 'Hello world';
str.search(/o/); // 4
str.search(/x/); // -1
32.3.3 String.prototype.includes
- 인수로 전달받은 문자열이 포함되어 있는지 확인하여 그 결과를 true/false로 반환함
const str = 'Hello world';
str.includes('Hello'); // true
str.includes(''); // true
str.includes('x'); // false
str.includes(); // false
// 문자열의 인덱스 3부터 포함되어 있는지 확인
str.includes('l', 3); // true
str.includes('H', 3); // false
32.3.4 String.prototype.startsWith
- 인수로 전달받은 문자열로 시작하는지 확인하여 그 결과를 true/false로 반환함
const str = 'Hello world';
str.startsWith('He'); // true
str.startsWith('x'); // false
// 문자열의 인덱스 5부터 시작되는 문자열이 ' '로 시작하는지 확인
str.startsWith(' ', 5); // true
32.3.5 String.prototype.endsWith
- 인수로 전달받은 문자열로 끝나는지 확인하여 그 결과를 true/false로 반환함
const str = 'Hello world';
str.endsWith('ld'); // true
str.endsWith('x'); // false
// 문자열의 처음부터 5자리까지('Hello')가 'lo'로 끝나는지 확인
str.endsWith('lo', 5); // true
32.3.6 String.prototype.chartAt
- 인수로 전달받은 인덱스에 위치한 문자를 검색하여 반환
- 인덱스가 문자열의 범위를 벗어난 정수인 경우 빈 문자열을 반환
const str = 'Hello';
for (let i = 0; i < str.length; i++) {
console.log(str.charAt(i)); // H e l l o
}
// 인덱스가 문자열의 범위를 벗어난 경우 빈 문자열을 반환함
str.charAt(5); // ''
32.3.7 String.prototype.substring
- 첫 번째 인수로 전달받은 인덱스에 위치하는 문자부터 두 번째 인수로 전달받은 인덱스에 위치하는 문자의 바로 이전 문자까지의 부분 문자열을 반환함
- 두 번째 인수는 생략 가능
: 이 경우 첫 번째 인수로 전달한 인덱스에 위치하는 문자부터 마지막 문자까지 부분 문자열을 반환함
! 첫 번째 인수는 두 번째 인수보다 작은 정수이어야 정상이지만,
다음과 같이 인수를 전달하여도 정상 동작함
1. 첫 번째 인수 > 두 번째 인수인 경우 두 인수는 교환됨2. 인수가 음수이거나 NaN인 경우 0으로 취급3. 인수가 문자열의 길이보다 큰 경우 인수는 문자열의 길이로 취급됨
const str = 'Hello World';
str.substring(4, 1); // 'ell'
str.substring(-2); // 'Hello World'
str.substring(1, 100); // 'ello World'
str.substring(20); // ''
32.3.8 String.prototype.slice
- substring 메서드와 동일하게 동작
- 단, 음수인 인수를 전달할 수 있음
- 음수인 인수를 전달하면 대상 문자열의 가장 뒤에서부터 시작하여 문자열을 잘라내어 반환
const str = 'Hello World';
str.substring(-5); // 'Hello World'
str.slice(-5); // 'World'
32.3.9 String.prototype.toUpperCase
- 모두 대문자로 변경한 문자열을 출력
const str = 'Hello World!';
str.toUpperCase(); // 'HELLO WORLD!'
32.3.10 String.prototype.toLowerCase
- 모두 소문자로 변경한 문자열을 출력
const str = 'Hello World!';
str.toLowerCase(); // 'hello world!'
32.3.11 String.prototype.trim
- 문자열 앞뒤에 공백 문자가 있을 경우 이를 제거한 문자열을 반환
- 앞 또는 뒤만 골라서 제거할 수도 있음
- 정규 표현식을 인수로 전달해서 공백 문자를 제거할 수도 있음
const str = ' foo ';
str.trim(); // 'foo'
const str = ' foo ';
str.trimStart(); // 'foo '
str.trimEnd(); // ' foo'
const str = ' foo ';
str.replace(/\s/g, ''); // 'foo'
str.replace(/^\s+/g, ''); // 'foo '
str.replace(/\s+$/g, ''); // ' foo'
32.3.12 String.prototype.repeat
- 인수로 전달받은 정수만큼 반복해 연결한 새로운 문자열을 반환
- 음수이면 RangeError
- 인수를 생략하면 기본값 0이 설정됨
const str = 'abc';
str.repeat(); // ''
str.repeat(0); // ''
str.repeat(1); // 'abc'
str.repeat(2); // 'abcabc'
str.repeat(2.5); // 'abcabc'
str.repeat(-1); // RangeError
32.3.13 String.prototype.replace
- 첫 번째 인수로 전달받은 문자열 또는 정규표현식을 검색해서 두 번째 인수로 전달한 문자열로 치환환 문자열을 반환함
- 검색된 문자열이 여럿 존재할 경우 첫 번째로 검색된 문자열만 치환
- 특수한 교체 패턴 가능
const str = 'Hello world';
str.replace('world', 'Lee'); // 'Hello Lee'
const str = 'Hello world world';
str.replace('world', 'Lee'); // 'Hello Lee world'
32.3.14 String.prototype.split
- 문자열을 구분한 후 분리된 각 문자열로 이루어진 배열을 반환함
- 인수로 빈 문자열을 전달하면 각 문자를 모두 분리함
- 인수를 생략하면 대상 문자열 전체를 단일 요소로 하는 배열을 반환
const str = 'How are you doing?';
str.split(' '); // ["How", "are", "you", "doing?"]
str.split(); // ["How are you doing?"]
CH33. 7번째 데이터 타입 Symbol
33.1 심벌이란?
- 변경 불가능한 원시 타입의 값
- 다른 값과 중복되지 않는 유일무이한 값
- 이름의 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용함
33.2 심벌 값의 생성
- Symbol 함수를 호출하여 생성
33.2.1 Symbol 함수
- new 연산자와 함께 호출하지 않음
const mySymbol = Symbol();
console.log(typeof mySymbol); // symbol
// 심벌 값은 외부로 노출되지 않아 확인할 수 없음
console.log(mySymbol); // Symbol()
new Symbol(); // TypeError
// 유일무이
const s1 = Symbol('my');
const s2 = Symbol('my');
console.log(s1 === s2); // false
- 암묵적으로 문자열이나 숫자 타입으로 변환되지 않음
- 단, 불리언 타입으로는 암묵적 변환이 됨 (if 문 등에서 확인)
const sb = Symbol();
console.log(sb + ''); // TypeError
console.log(!!sb); // true
33.2.1 Symbol.for / Symbol.keyFor 메서드
- Symbol.for 메서드는 인수로 전달받은 문자열을 키로 사용하여 키와 심벌 값의 쌍들이 저장되어 있는 전역 심벌 레지스트리에서 해당 키와 일치하는 심벌 값을 검색함: 검색에 성공하면 새로운 심벌 값을 생성하지 않고 검색된 심벌 값을 반환: 검색 실패 시 새로운 심벌 값을 생성하여 Symbol.for 메서드의 인수로 전달된 키로 전역 심벌 레지스트리에 저장한 후, 생성된 심벌 값을 반환
const s1 = Symbol.for('mySymbol'); // 새로 생성
const s2 = Symbol.for('mySymbol'); // 검색 성공, 해당 심벌 값
console.log(s1 === s2); // true
- Symbol.keyFor 메서드를 사용하면 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있음
const s1 = Symbol.for('mySymbol'); // 새로 생성
Symbol.keyFor(s1); // mySymbol, 심벌 값의 키 추출
// Symbol 함수를 호출하여 생성한 심벌 값은 전역 심벌 레지스트리에 등록되어 관리되지 않음
const s2 = Symbol.for('mySymbol');
Symbol.keyFor(s2); // undefined
33.3 심벌과 상수
- 값에는 특별한 의미가 없고, 상수 이름 자체에 의미가 있는 경우, 유일무이한 심벌 값 사용 가능
const Dir = {
UP: Symbol('up'),
DOWN: Symbol('down'),
LEFT: Symbol('left'),
RIGHT: Symbol('right')
};
const mydir = Dir.UP;
if (mydir === Dir.UP) console.log('You are going UP.');
33.4 심벌과 프로퍼티 키
- 접근 시 대괄호 사용
- 어떤 프로퍼티 키와도 충돌할 위험이 없는 심벌 값의 프로퍼티
const obj = {
[Symbol.for('mySymbol')]: 1
};
obj[Symbol.for('mySymbol')]; // 1
33.5 심벌과 프로퍼티 은닉
- 심벌 값으로 생성한 프로퍼티는 for문이나 Object.keys 메서드로 찾을 수 없음
- 외부에 노출할 필요가 없는 프로퍼티를 은닉할 수 있음
const obj = {
[Symbol('mySymbol')]: 1
};
for (const key in obj) {
console.log(key); // 아무것도 출력 안 됨
}
console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertyNames(obj)); // []
33.6 심벌과 표준 빌트인 객체 확장
- 일반적으로 표준 빌트인 객체에 사용자 정의 메서드를 직접 추가해 확장하는 것은 권장하지 않음
- 읽기 전용으로 사용하는 것 추천
33.7 Well-known Symbol
- 자바스크립트가 기존 제공하는 빌트인 심벌 값을 ECMAScript 사양에서 Well-known Symbol이라 함
'2022-2 웹개발 스터디' 카테고리의 다른 글
[모던 JS] CH 39. DOM (1) | 2022.11.13 |
---|---|
[모던 JS] CH 38. 브라우저의 렌더링 과정 (0) | 2022.11.12 |
[모던 JS] CH 28. Number, CH 29. Math, CH 30. Date, CH 31. RegExp (#16) (0) | 2022.11.05 |
[모던 JS] CH27. 배열 (#15) (0) | 2022.11.05 |
[모던 JS] CH26. ES6 함수의 추가 기능 (#14) (0) | 2022.11.02 |