이안의 평일코딩

32장 String & 33장 Symbol & 34장 이터러블 본문

Study/JS Diver

32장 String & 33장 Symbol & 34장 이터러블

이안92 2021. 8. 3. 19:39
반응형

32

 

p.594

- String 객체의 메서드는 언제나 새로운 문자열을 반환한다. 문자열은 변경 불가능(immutable)한 원시 값이기 때문에 String 래퍼 객체도 읽기 전용(read only)객체로 제공된다.

 

> String 메서드

- String.prototype.indexOf: 인수로 전달받은 문자열 검색하여 첫 번째 인덱스 반환, 검색 실패시 -1 반환

- String.prototype.includes: ES6에서 도입된 메서드로 문자열 포함 결과를 true 또는 false로 반환한다.

if (str.indexOf('Hello') !== -1 {
  // 문자열 str에 'Hello'가 포함되어 있는 경우에 처리할 내용
}

if (str.includes('Hello')) {
  // 문자열 str에 'Hello'가 포함되어 있는 경우에 처리할 내용
}

- String.prototype.search: 인수로 전달받은 정규 표현식과 매치하는 문자열을 검색하여 일치하는 문자열의 인덱스 반환, 검색 실패시 -1 반환

- String.prototype.startsWith: 대상 문자열이 인수로 전달받은 문자열로 시작하는지 확인하여 true 또는 false로 반환

- String.prototype.endsWith: 대상 문자열이 인수로 전달받은 문자열로 끝나는지 확인하여 true 또는 false로 반환

- String.prototype.charAt: 대상 문자열에서 인수로 전달받은 인덱스에 위치한 문자를 검색하여 반환

- String.prototype.substring: 첫 번째 인수 인덱스 문자부터 두 번째 인수 인덱스 문자의 바로 이전 문자까지 문자열 반환. 두 번째 인수 생략시 마지막 문자까지 문자열 반환

- String.prototype.slice: substring과 동일하게 동작하지만 음수 인수도 전달 가능하고 음수는 문자열 가장 뒤에서부터 잘라내어 반환

const str = 'hello world';

str.substring(0, 5); // 'hello'
str.slice(0, 5); // 'hello'

// 인수 < 0 또는 NaN인 경우 0으로 취급된다.
str.substring(-5); // 'hello world'
// slice 메서드는 음수인 인수를 전달할 수 있다. 뒤에서 5자리를 잘라내어 반환
str.slice(-5); // world

- String.prototype.toUpperCase: 문자열을 모두 대문자로 변경한 문자열 반환

- String.prototype.toLowerCase: 문자열을 모두 소문자로 변경한 문자열 반환

- String.prototype.trim: 문자열 앞뒤에 공백 문자가 있을 경우 이를 제거한 문자열 반환

- String.prototype.repeat: 인수로 전달받은 정수만큼 반복, 인수 생략 또는 정수가 0이면 빈 문자열 반환, 음수면 RangeError 발생

- String.prototype.replace: 첫 번째 인수로 전달받은 문자열, 정규표현식을 두 번째 인수로 전달한 문자열로 치환한 문자열 반환

- String.prototype.split: 첫 번째 인수로 전달한 문자열, 정규표현식을 구분한 후 분리된 각 문자열로 배열을 반환

// 인수로 전달받은 문자열을 역순으로 뒤집는다
function reverseString(str) {
  return str.split('').reverse().join('');
}

reverseString('Hello world!'); // '!dlrow olleH'

 

33

 

p.605

- 심벌 값은 Symbol 함수를 호출하여 생성한다. 다른 원시값, 즉 문자열, 숫자 불리언, undefined, null 타입의 값은 리터럴 표기법을 통해 값을 생성할 수 있지만 심벌 값은 Symbol 함수를 호출하여 생성해야 한다. 다른 값과 절대 중복되지 않는 유일무이한 값이다.

// Symbol 함수를 호출하여 유일무이한 심벌 값을 생성한다
const mySymbol = Symbol();
console.log(typeof mySymbol); // symbol

// 심벌 값은 외부로 노출되지 않아 확인할 수 없다
console.log(mySymbol); // Symbol()

 

p.606

- Symbol 함수는 String, Number, Boolean 생성자 함수와는 달리 new 연산자와 함께 호출하지 않는다. 선택적으로 문자열을 인수로 전달할 수 있고 심벌 값에 대한 설명으로 디버깅 용도로만 사용되며 심벌값 생성에 어떠한 영향도 주지 않는다. 코드 주석과 비슷한 역할로 콘솔 찍었을 때 편하게 보기 위한 용도이다.

new Symbol(); // TypeError: Symbol is not a constructor

// 심벌 값에 대한 설명이 같더라도 유일무이한 심벌 값을 생성한다
const mySymbol1 = Symbol('mySymbol');
const mySymbol2 = Symbol('mySymbol');

console.log(mySymbol1 === mySymbol2); // false

 

p. 607

- Symbol.for 메서드는 인수로 전달받은 문자열을 키로 사용하여 키와 심벌 값의 쌍들이 저장되어 있는 전역 심벌 레지스트리에서 해당 키와 일치하는 심벌 값을 검색한다. Symbol.for 메서드를 사용하면 심벌 값을 단 하나만 생성하여 전역 심벌 레지스트리를 통해 공유할 수 있다.

// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값을 생성
const s1 = Symbol.for('mySymbol');
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 있으면 해당 심벌 값을 반환
const s2 = Symbol.for('mySymbol');

console.log(s1 === s2); // true

 

p.608

- Symbol.keyFor 메섣를 사용하면 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있다.

// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값을 생성
const s1 = Symbol.for('mySymbol');
// 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출
Symbol.keyFor(s1); // mySymbol

// Symbol 함수를 호출하여 생성한 심벌 값은 전역 심벌 레지스트리에 등록되어 관리되지 않는다.
const s2 = Symbol('foo');
// 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출
Symbol.keyFor(s2); // undefined

 

p.610

- 심벌 값을 프로퍼티 키로 사용하려면 프로퍼티 키로 사용할 심벌 값에 대괄호를 사용해야 한다. 프로퍼티에 접근할 때도 마찬가지로 대괄호를 사용해야 한다.

const obj = {
  // 심벌 값으로 프로퍼티 키를 생성
  [Symbol.for('mySymbol')]: 1
};

obj[Symbol.for('mySymbol')]; // 1

 

- 기본적으로 Symbol은 필드를 객체 내부에 숨기기 위해서 사용하고 private 필드라고 직관적으로 알려 줄 수 있다. Symbol을 이용해서 내부 변수를 선언했다면 우연히 중복되게 겹쳐 실수로 내부 필드를 덮어버리는 것을 방지할 수 있다. Symbol을 통해 해당 변수에 추가적인 의미를 줄 수 있고 키 값이 겹쳐서 꼬이는걸 방지해줄 수 있다.

 

 

34

p.614

- ES6에서 도입된 이터레이션 프로토콜(iteration protocol)은 데이터 컬렉션(자료구조)를 순회하기 위한 프로토콜이다. 이터레이션 프로토콜을 준수한 객체는 for...of문으로 순회할 수 있고 Spread 문법, 배열 디스트럭처링 할당의 대상으로 사용할 수 있다. 이터레이션 프로토콜에는 이터러블 프로토콜(interable protocol)과 이터레이터 프로토콜(iterator protocol)이 있다.

 

p.615

- 이터러블 프로토콜을 준수한 객체를 이터러블이라 한다. 즉, 이터러블은 Symbol.iterator 메소드를 구현하거나 프로토타입 체인에 의해 상속한 객체를 말한다. Symbol.iterator 메소드는 이터레이터를 반환한다.

const array = [1, 2, 3];

// 배열은 Symbol.iterator 메소드를 소유한다.
// 따라서 배열은 이터러블 프로토콜을 준수한 이터러블이다.
console.log(Symbol.iterator in array); // true

// 이터러블 프로토콜을 준수한 배열은 for...of 문에서 순회 가능하다.
for (const item of array) {
  console.log(item);
}

 

p.616

- 이터레이터 프로토콜은 next 메서드를 소유하며 value, done 프로퍼티를 갖는 이터레이터 리절트(iterator result) 객체를 반환한다.

// 배열은 이터러블 프로토콜을 준수한 이터러블이다.
const array = [1, 2, 3];

// Symbol.iterator 메소드는 이터레이터를 반환한다.
const iterator = array[Symbol.iterator]();

// 이터레이터 프로토콜을 준수한 이터레이터는 next 메소드를 갖는다.
console.log('next' in iterator); // true

// 이터레이터의 next 메소드를 호출하면 value, done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환한다.
// next 메소드를 호출할 때 마다 이터러블을 순회하며 이터레이터 리절트 객체를 반환한다.
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}

 

p.617

- 빌트인 이터러블: Array, String, Map, Set, TypedArray, Arguments, DOM data structure(NodeList, HTMLCollection)

 

p.618

// for ... of 문은 이터러블을 순회하면서 이터러블의 요소를 변수에 할당한다
for (변수선언문 of 이터러블) { ... }
// for ... of 문은 for ... in 문의 형식과 매우 유사하다
for (변수선언문 in 객체) { ... }

 

p. 619

for (const item of [1, 2, 3]) {
  // item 변수에 순차적으로 1, 2, 3이 할당된다
  console.log(item); // 1 2 3
}

- for ... of 문의 내부 동작을 for 문으로 표현하면 다음과 같다.

// 이터러블
const iterable = [1, 2, 3];

// 이터러블의 Symbol.iterator 메서드를 호출하여 이터레이터 생성
const iterator = iterable[Symbol.iterator]();

for (;;) {
  // 이터레이터의 next 메소드를 호출하여 이터러블을 순회한다
  // 이때 next 메서드는 이터레이터 리절트 객체를 반환한다
  const res = iterator.next();

  // next 메소드가 반환하는 이터레이터 리절트 객체의 done 프로퍼티가 true가 될 때까지 반복한다.
  if (res.done) break;
  
  // 이터레이터 리절트 객체의 value 프로퍼티 값을 item 변수에 할당한다.
  const item = res.value;
  console.log(item); // 1 2 3
}

 

반응형
Comments