[FE Study] ES6 Symbol & Generator

leewolΒ·2022λ…„ 6μ›” 10일
0

JavaScript

λͺ©λ‘ 보기
3/3

πŸ–₯ ES6 - Symbol & Generator

Symbol(μ‹¬λ²Œ)

기쑴에 μ‘΄μž¬ν•˜λ˜ 6개의 νƒ€μž…(String, Number, Boolean, undefined, null, Object) λ‹€μŒμœΌλ‘œ ES6μ—μ„œ λ„μž…λœ λ³€κ²½ λΆˆκ°€λŠ₯ν•œ μ›μ‹œ νƒ€μž…μ˜ κ°’

  • λ‹€λ₯Έ κ°’κ³Ό μ ˆλŒ€ μ€‘λ³΅λ˜μ§€ μ•ŠλŠ” μœ μΌλ¬΄μ΄ν•œ κ°’
    • 객체 ν”„λ‘œνΌν‹° ν‚€λ‘œ μ‚¬μš© κ°€λŠ₯
  • 생성
    • Symbol ν•¨μˆ˜ 호좜 (λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•, new μ—°μ‚°μž 이용 X)
    • μ΄λ•Œ μƒμ„±λœ μ‹¬λ²Œ 값은 μ™ΈλΆ€λ‘œ λ…ΈμΆœλ˜μ§€ μ•Šμ•„ 확인할 수 μ—†μŒ
  • 객체처럼 μ ‘κ·Όν•˜λ©΄ μ•”λ¬΅μ μœΌλ‘œ 래퍼 객체 생성
    • 래퍼 객체(wrapper object)λŠ” λ¬Έμžμ—΄, 숫자, λΆˆλ¦¬μ–Έ, μ‹¬λ²Œ 같은 μ›μ‹œ 값에 λŒ€ν•΄ 객체처럼 μ ‘κ·Όν•˜λ©΄ μƒμ„±λ˜λŠ” μž„μ‹œ 객체
    • μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진이 μΌμ‹œμ μœΌλ‘œ μ›μ‹œ 값을 μ—°κ΄€λœ 객체λ₯Ό μƒμ„±ν•˜μ—¬ μƒμ„±λœ 객체둜 ν”„λ‘œνΌν‹°μ— μ ‘κ·Όν•˜κ±°λ‚˜ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κ³  λ‹€μ‹œ μ›μ‹œ κ°’μœΌλ‘œ 되돌림
  • μ•”λ¬΅μ μœΌλ‘œ Stringμ΄λ‚˜ Number νƒ€μž…μœΌλ‘œ λ³€ν™˜λ˜μ§€ μ•ŠμŒ, Boolean νƒ€μž…μœΌλ‘œλŠ” κ°€λŠ₯
  • Well-known Symbol : μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ κΈ°λ³Έ 제곡 ν•˜λŠ” 빌트인 Symbol κ°’
    • μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄λΆ€ 엔진 μ•Œκ³ λ¦¬μ¦˜μ— μ‚¬μš©
// Symbol ν•¨μˆ˜ ν˜ΈμΆœν•˜μ—¬ 생성
// μ„ νƒμ μœΌλ‘œ λ¬Έμžμ—΄μ„ 인수둜 전달 κ°€λŠ₯ (μ‹¬λ²Œ 값에 λŒ€ν•œ μ„€λͺ…, 디버깅 μš©λ„)
const mySymbol1 = Symbol("mine");
const mySymbol2 = Symbol("mine");

// 값은 μ™ΈλΆ€λ‘œ λ…ΈμΆœλ˜μ§€ μ•Šμ•„ μ•Œ 수 μ—†μŒ
console.log(typeof mySymbol1, mySymbol1); //symbol, Symbol()
console.log(mySymbol1 === mySymbol2); //false
console.log(mySymbol1.description); //'mine'
console.log(mySymbol1 + 1); //TypeError: Cannot convert a Symbol value to a number
console.log(mySymbol1 + ""); //TypeError: Cannot convert a Symbol value to a string
console.log(!mySymbol1); //true

Symbol λ©”μ„œλ“œ

  • Symbol.for : 인수둜 전달받은 λ¬Έμžμ—΄μ„ key둜 μ‚¬μš©ν•˜μ—¬ key와 Symbol κ°’μ˜ μŒλ“€μ΄ μ €μž₯λ˜μ–΄ μžˆλŠ” μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬(global symbol registry)μ—μ„œ ν•΄λ‹Ή key와 μΌμΉ˜ν•˜λŠ” Symbol κ°’ 검색

    • 성곡 μ‹œ, μƒˆλ‘œμš΄ Symbol κ°’ λ°˜ν™˜ν•˜μ§€ μ•Šκ³  κ²€μƒ‰λœ Symbol κ°’ λ°˜ν™˜
    • μ‹€νŒ¨ μ‹œ, μƒˆλ‘œμš΄ Symbol κ°’ μƒμ„±ν•˜μ—¬ ν•΄λ‹Ή λ©”μ„œλ“œ 인수 key둜 μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— μ €μž₯ ν›„ μƒμ„±λœ Symbol κ°’ λ°˜ν™˜
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ „μ—­μ—μ„œ μ€‘λ³΅λ˜μ§€ μ•ŠλŠ” Symbol 값을 단 ν•˜λ‚˜λ§Œ μƒμ„±ν•˜μ—¬ μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ—μ„œ 곡유 κ°€λŠ₯

  • Symbol.keyFor : μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— μ €μž₯된 Symbol κ°’μ˜ ν‚€ μΆ”μΆœ

const s1 = Symbol.for("mine"); // μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— μƒˆλ‘œ 생성
const s2 = Symbol.for("mine"); // μ €μž₯된 Symbol κ°’ λ°˜ν™˜

console.log(s1 === s2); //true
Symbol.keyFor(s1); //'mine'

Symbolκ³Ό Property 은닉

  • Symbol 값을 ν”„λ‘œνΌν‹° ν‚€λ‘œ μ‚¬μš©ν•˜μ—¬ μƒμ„±ν•œ ν”„λ‘œνΌν‹°λŠ” for ... in, Object.keys, Object.getOwnPropertyNames λ©”μ„œλ“œλ‘œ 찾을 수 μ—†μŒ
  • Object.getOwnPropertySymbols μ΄μš©ν•˜μ—¬ ν”„λ‘œνΌν‹° μ°ΎκΈ° κ°€λŠ₯

Generator (μ œλ„ˆλ ˆμ΄ν„°)

μ½”λ“œ 블둝 싀행을 μΌμ‹œ 쀑지 ν–ˆλ‹€κ°€ ν•„μš”ν•œ μ‹œμ μ— μž¬κ°œν•  수 μžˆλŠ” νŠΉμˆ˜ν•œ ν•¨μˆ˜
일반 ν•¨μˆ˜μ²˜λŸΌ μ½”λ“œ 블둝을 μ‹€ν–‰ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, μ œλ„ˆλ ˆμ΄ν„° 객체(μ΄ν„°λŸ¬λΈ”μ΄λ©΄μ„œ λ™μ‹œμ— μ΄ν„°λ ˆμ΄ν„°)λ₯Ό 생성해 λ°˜ν™˜

  • vs. 일반 ν•¨μˆ˜
    • ν•¨μˆ˜ ν˜ΈμΆœμžμ—κ²Œ ν•¨μˆ˜ μ‹€ν–‰ μ œμ–΄κΆŒ 양도(yield) κ°€λŠ₯
      • 일반 ν•¨μˆ˜λŠ” ν•¨μˆ˜ 호좜 이후 ν•¨μˆ˜λ₯Ό 일괄 μ‹€ν–‰ (ν˜ΈμΆœμžλŠ” μ œμ–΄ λΆˆκ°€)
    • ν•¨μˆ˜ ν˜ΈμΆœμžμ™€ ν•¨μˆ˜μ˜ μƒνƒœλ₯Ό 주고받을 수 있음
    • μ œλ„ˆλ ˆμ΄ν„° 객체 λ°˜ν™˜
  • function* ν‚€μ›Œλ“œλ‘œ μ„ μ–Έ, ν•˜λ‚˜ μ΄μƒμ˜ yield ν‘œν˜„μ‹ 포함
    • ν™”μ‚΄ν‘œ ν•¨μˆ˜(=>), new μ—°μ‚°μž μ‚¬μš© X
  • ν”„λ‘œλ―ΈμŠ€ 후속 처리 λ©”μ„œλ“œ then/catch/finally 없이 비동기 처리 κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λ„λ‘ κ΅¬ν˜„ν•  수 있음 (Deep Dive 878p~ μ°Έμ‘°)
    • κ·ΈλŸ¬λ‚˜ ES8에 λ„μž…λœ async/awaitκ°€ 더 κ°„λ‹¨ν•˜κ³  가독성이 μ’‹μŒ!

λ©”μ„œλ“œ

  • next : μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜μ˜ yield ν‘œν˜„μ‹κΉŒμ§€ μ½”λ“œ 블둝을 μ‹€ν–‰ν•˜κ³ , yield 된 값을 value ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ, falseλ₯Ό done ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ κ°–λŠ” μ΄ν„°λ ˆμ΄ν„° 리절트 객체 λ°˜ν™˜
  • return : 인수둜 전달받은 값을 value ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ, trueλ₯Ό done ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ κ°–λŠ” μ΄ν„°λ ˆμ΄ν„° 리절트 객체 λ°˜ν™˜
  • throw : 인수둜 전달받은 μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚€κ³ , undefinedλ₯Ό value ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ, trueλ₯Ό done ν”„λ‘œνΌν‹° κ°’μœΌλ‘œ κ°–λŠ” μ΄ν„°λ ˆμ΄ν„° 리절트 객체 λ°˜ν™˜
  • done ν”„λ‘œνΌν‹° : μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜κ°€ λκΉŒμ§€ μ‹€ν–‰λ˜μ—ˆλŠ”κ°€
function* genFunc() {
  try {
    yield 1; // μ—¬κΈ°κΉŒμ§€
    yield 2;
    yield 3;
  } catch (e) {
    console.error(e);
  }
}

const generator = genFunc();

console.log(generator.next()); //{value: 1, done: false}
console.log(generator.next()); //{value: 2, done: false}
console.log(generator.throw("Error!")); //{value: undefined, done: true}, λλ‚˜κΈ° 전에 μ‹€ν–‰ν•΄μ•Ό
console.log(generator.return("End!")); //{value: 'End!', done: true}

/******** next에 인수 전달 *********/
function* genFunc() {
  const x = yield 1;
  const y = yield x + 10;
  return x + y;
}

const generator = genFunc(0);

//처음 ν˜ΈμΆœν•˜λŠ” next λ©”μ„œλ“œ 인수 전달은 λ¬΄μ‹œ
let res = generator.next(100);
console.log(res); //{value: 1, done: false}

res = generator.next(10);
console.log(res); //{value: 20, done: false}

res = generator.next(20);
console.log(res); //{value: 30, done: true}

//λ¬΄ν•œ μ΄ν„°λŸ¬λΈ” infiniteFiboλ₯Ό μƒμ„±ν•˜λŠ” μ œλ„ˆλ ˆμ΄ν„° ν•¨μˆ˜
const infiniteFibo = (function* () {
  let [pre, cur] = [0, 1];

  while (true) {
    [pre, cur] = [cur, pre + cur];
    yield cur;
  }
})();

for (const num of infiniteFibo) {
  if (num > 10000) break;
  console.log(num); // 1 2 3 5 8 ... 2584 4181 6765
}

μ°Έκ³ 

λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive
ES6 (ES2015) 의 νŠΉμ§•λ“€

profile
κ°„μ‚΄κ°„μ£½ κ°œμ‚΄κ°œμ£½

0개의 λŒ“κΈ€