λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
javascript/πŸ“– study

[7μ£Όμ°¨ μŠ€ν„°λ””]33μž₯-Symbol

by HomieKim 2022. 3. 27.

7번째 데이터 νƒ€μž… Symbol

μ‹¬λ²Œμ΄λž€?

  • μžλ°”μŠ€ν¬λ¦½νŠΈμ—λŠ” 6개의 데이터 νƒ€μž…μ΄ μžˆμŠ΅λ‹ˆλ‹€.
    • λ¬Έμžμ—΄
    • 숫자
    • λΆˆλ¦¬μ–Έ
    • undefined
    • null
    • 객체 νƒ€μž…
  • μ‹¬λ²Œ(symbol)은 ES6μ—μ„œ λ„μž…λœ 7번째 데이터 νƒ€μž…μœΌλ‘œ λ³€κ²½ λΆˆκ°€λŠ₯ν•œ μ›μ‹œνƒ€μž…μ˜ κ°’
  • λ‹€λ₯Έ κ°’κ³Ό μ€‘λ³΅λ˜μ§€ μ•ŠλŠ” 유일 λ¬΄μ΄ν•œ κ°’μœΌλ‘œ 이름 좩돌 μœ„ν—˜μ΄ μ—†λŠ” μœ μΌν•œ ν”„λ‘œνΌν‹° ν‚€λ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€.

    ν”„λ‘œνΌν‹° ν‚€λ‘œ μ‚¬μš©ν•  수 μžˆλŠ” 값은 빈 λ¬Έμžμ—΄μ„ ν¬ν•¨ν•˜λŠ” λͺ¨λ“  λ¬Έμžμ—΄ λ˜λŠ” μ‹¬λ²Œ 값이닀.

μ‹¬λ²Œ κ°’μ˜ 생성

Symbol ν•¨μˆ˜

  • Symbol값은 λ‹€λ₯Έ μ›μ‹œκ°’κ³Ό λ‹€λ₯΄κ²Œ λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μ΄ μ—†κ³  Symbol ν•¨μˆ˜λ₯Ό 톡해 μƒμ„±ν•©λ‹ˆλ‹€
  • μ΄λ•Œ μƒμ„±λœ μ‹¬λ²Œκ°’μ€ μ™ΈλΆ€λ‘œ λ…ΈμΆœλ˜μ§€ μ•Šκ³ , λ‹€λ₯Έ κ°’κ³Ό μ ˆλŒ€ μ€‘λ³΅λ˜μ§€ μ•ŠλŠ” μœ μΌλ¬΄μ΄ν•œ κ°’
// ν•¨μˆ˜ ν˜ΈμΆœμ„ 톡해 생성
const mySymbol = Symbol();
console.log(type of my Symbol); // symbol

// μ‹¬λ²Œ 값은 μ™ΈλΆ€λ‘œ λ…ΈμΆœλ˜μ§€ μ•Šμ•„ 확인이 λΆˆκ°€
console.log(mySymbol); // Symbol()

// μƒμ„±μž ν•¨μˆ˜μ²˜λŸΌ λ³΄μ΄μ§€λ§Œ
// new μ—°μ‚°μžμ™€ ν•¨κ»˜ μ‚¬μš©μ‹œ κ°μ²΄λŠ” μƒμ„±λ˜μ§€λ§Œ μ‹¬λ²Œ 값은 λ³€κ²½λΆˆκ°€λŠ₯ν•œ μ›μ‹œκ°’
new Symbol(); // TypeError : Symbol is not a constructor
  • Symbol ν•¨μˆ˜μ—λŠ” μ„ νƒμ μœΌλ‘œ λ¬Έμžμ—΄ 인수λ₯Ό 전달할 수 μžˆμŠ΅λ‹ˆλ‹€.
  • μ „λ‹¬λœ λ¬Έμžμ—΄μ€ μƒμ„±λœ μ‹¬λ²Œ κ°’μ—λŒ€ν•œ μ„€λͺ…μœΌλ‘œ 디버깅 μš©λ„λ‘œλ§Œ μ‚¬μš©λ©λ‹ˆλ‹€.
  • μ‹¬λ²Œ 값도 λ¬Έμžμ—΄, 숫자 , λΆˆλ¦¬μ–Έ κ³Ό 같이 객체처럼 μ ‘κ·Ό μ‹œ μ•”λ¬΅μ μœΌλ‘œ 래퍼객체λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.
const mySymbol = Symbol('mySymbol');
// 객체 처럼 μ ‘κ·Ό μ‹œ 래퍼 객체λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.
console.log(mySymbol.description); // mySymbol
console.log(mySymbol.toString()); // Symbol(mySymbol)
  • μ‹¬λ²Œ 값은 μ•”λ¬΅μ μœΌλ‘œ λ¬Έμžμ—΄μ΄λ‚˜ 숫자 νƒ€μž…μœΌλ‘œ λ³€ν™˜λ˜μ§€ μ•ŠλŠ”λ‹€. 단, λΆˆλ¦¬μ–Έ νƒ€μž…μœΌλ‘œλŠ” μ•”λ¬΅μ μœΌλ‘œ νƒ€μž… λ³€ν™˜ λœλ‹€.
const mySymbol = Symbol();
// λΆˆλ¦¬μ–ΈμœΌλ‘œ 암묡적 νƒ€μž…λ³€ν™˜μ΄ λ˜λ―€λ‘œ if문으둜 쑴재 확인 κ°€λŠ₯
if(mySymbol) console.log('My Symbol is not empty');

Symbol.for / Symbol.keyFor λ©”μ„œλ“œ

Symbol.for

  • Symbol.for λ©”μ„œλ“œλŠ” 인수둜 전달받은 λ¬Έμžμ—΄μ„ ν‚€λ‘œ μ‚¬μš©ν•˜μ—¬ 킀와 μ‹¬λ²Œ κ°’μ˜ μŒλ“€μ΄ μ €μž₯λ˜μ–΄ μžˆλŠ” μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬ μ—μ„œ ν•΄λ‹Ή 킀와 μΌμΉ˜ν•˜λŠ” μ‹¬λ²Œ 값을 κ²€μƒ‰ν•œλ‹€.

    • 검색에 μ„±κ³΅ν•˜λ©΄ μƒˆλ‘œμš΄ μ‹¬λ²Œ 값을 μƒμ„±ν•˜μ§€ μ•Šκ³  검색돀 μ‹¬λ²Œ 값을 λ°˜ν™˜ ν•œλ‹€.
    • 검색에 μ‹€νŒ¨ν•˜λ©΄ μƒˆλ‘œμš΄ μ‹¬λ²Œκ°’μ„ μƒμ„±ν•˜μ—¬ Symbol.for λ©”μ„œλ“œμ˜ 인수둜 μ „λ‹¬λœ ν‚€λ‘œ μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— μ €μž₯ν•œ ν›„,μƒμ„±λœ μ‹¬λ²Œ 값을 λ°˜ν™˜ ν•œλ‹€.
// μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— mySymbolμ΄λΌλŠ” ν‚€λ‘œ μ €μž₯된 μ‹¬λ²Œ 값이 μ—†μœΌλ©΄ μƒˆλ‘œμš΄ μ‹¬λ²Œ 값을 생성
const s1 = Symbol.for('mySymbol');
// μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— mySymbolμ΄λΌλŠ” ν‚€λ‘œ μ €μž₯된 μ‹¬λ²Œ 값이 있으면 ν•΄λ‹Ή μ‹¬λ²Œ 값을 λ°˜ν™˜
const s2 = Symbol.for('mySymbol');

console.log(s1 === s2); // true
  • Symbol.forλ₯Ό μ‚¬μš©ν•˜λ©΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ „μ—­μ—μ„œ μ€‘λ³΅λ˜μ§€ μ•ŠλŠ” 유일 λ¬΄μ΄ν•œ μƒμˆ˜μΈ μ‹¬λ²Œκ°’μ„ 단 ν•˜λ‚˜λ§Œ μƒμ„±ν•˜μ—¬ μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬λ₯Ό 톡해 곡유 ν•  수 μžˆλ‹€.

Symbol.keyFor

  • Symbol.keyFor λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— μ €μž₯된 μ‹¬λ²Œ κ°’μ˜ ν‚€λ₯Ό μΆ”μΆœν•  수 μžˆλ‹€.
// μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— mySymbolμ΄λΌλŠ” ν‚€λ‘œ μ €μž₯된 μ‹¬λ²Œ 값이 μ—†μœΌλ©΄ μƒˆλ‘œμš΄ μ‹¬λ²Œ 값을 생성
const s1 = Symbol.for('mySymbol');
// μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— μ €μž₯된 μ‹¬λ²Œ κ°’μ˜ ν‚€λ₯Ό μΆ”μΆœ
Symbol.keyFor(s1); // -> mySymbol

// Symbol ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μƒμ„±ν•œ μ‹¬λ²Œ 값은 μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— λ“±λ‘λ˜μ–΄ κ΄€λ¦¬λ˜μ§€ μ•ŠλŠ”λ‹€.
const s2 = Symbol('foo');
// μ „μ—­ μ‹¬λ²Œ λ ˆμ§€μŠ€νŠΈλ¦¬μ— μ €μž₯된 μ‹¬λ²Œ κ°’μ˜ ν‚€λ₯Ό μΆ”μΆœ
Symbol.keyFor(s2); // -> undefined

μ‹¬λ²Œκ³Ό μƒμˆ˜

  • μƒμˆ˜λ₯Ό μ •μ˜ ν•  λ•Œ κ°’μ—λŠ” νŠΉλ³„ν•œ μ˜λ―Έκ°€ μ—†κ³  μƒμˆ˜ 이름 μžμ²΄μ— μ˜λ―Έκ°€ μžˆλŠ” κ²½μš°κ°€ μžˆλ‹€.
  • μ΄λ•Œ λ¬Έμ œλŠ” μƒμˆ˜ 값이 λ³€κ²½λ˜κ±°λ‚˜ λ‹€λ₯Έ λ‹€λ₯Έ λ³€μˆ˜ κ°’κ³Ό 쀑볡 될 수 μžˆλ‹€λŠ” 것
  • 이런 경우 쀑볡될 κ°€λŠ₯ 성이 μ—†λŠ” μ‹¬λ²Œ 값을 μ‚¬μš©ν•  수 μžˆλ‹€.
// μœ„, μ•„λž˜, μ™Όμͺ½, 였λ₯Έμͺ½μ„ λ‚˜νƒ€λ‚΄λŠ” μƒμˆ˜λ₯Ό μ •μ˜ν•œλ‹€.
// 쀑볡될 κ°€λŠ₯성이 μ—†λŠ” μ‹¬λ²Œ κ°’μœΌλ‘œ μƒμˆ˜ 값을 μƒμ„±ν•œλ‹€.
const Direction = {
  UP: Symbol('up'),
  DOWN: Symbol('down'),
  LEFT: Symbol('left'),
  RIGHT: Symbol('right')
};

const myDirection = Direction.UP;

if (myDirection === Direction.UP) {
  console.log('You are going UP.');
}

μ°Έκ³ 

enum

  • enum은 λͺ…λͺ…λœ 숫자 μƒμˆ˜μ˜ μ§‘ν•©μœΌλ‘œ μ—΄κ±°ν˜•(enumerated type)이라고 λΆ€λ₯Έλ‹€.
  • μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” enum을 μ§€μ›ν•˜μ§€ μ•Šμ§€λ§Œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλ‚˜ c, java λ“± λ‹€λ₯Έ μ–Έμ–΄μ—μ„œ 지원
  • μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 객체 동결을 톡해 객체변경을 방지해 enum을 흉내내어 μ‚¬μš©κ°€λŠ₯
const Direction = Object.freeze({
    UP : Symbol('up'),
    DOWN: Symbol('down'),
    LEFT: Symbol('left'),
    RIGHT: Symbol('right')
});

μ‹¬λ²Œκ³Ό ν”„λ‘œνΌν‹° ν‚€

ν”„λ‘œνΌν‹° ν‚€λŠ” 빈 λ¬Έμžμ—΄μ„ ν¬ν•¨ν•˜λŠ” λͺ¨λ“  λ¬Έμžμ—΄ λ˜λŠ” μ‹¬λ²Œ κ°’μœΌλ‘œ λ§Œλ“€ 수 μžˆλ‹€.

  • μ‹¬λ²Œ 값을 ν”„λ‘œνΌν‹° ν‚€λ‘œ μ‚¬μš©ν•˜λ €λ©΄ ν”„λ‘œνΌν‹° ν‚€λ‘œ μ‚¬μš©ν•  μ‹¬λ²Œ 값에 λŒ€κ΄„ν˜Έλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
  • μ‹¬λ²Œλ‘œ μƒμ„±ν•œ ν”„λ‘œνΌν‹°μ— μ ‘κ·Όν•  λ•Œλ„ λ§ˆμ°¬κ°€μ§€λ‘œ λŒ€κ΄„ν˜Έλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
const obj = {
  // μ‹¬λ²Œ κ°’μœΌλ‘œ ν”„λ‘œνΌν‹° ν‚€λ₯Ό 생성
  [Symbol.for('mySymbol')]: 1
};

obj[Symbol.for('mySymbol')]; // -> 1
  • μ‹¬λ²Œ 값은 μœ μΌλ¬΄μ΄ν•œ κ°’μ΄λ―€λ‘œ μ‹¬λ²Œ κ°’μœΌλ‘œ ν”„λ‘œνΌν‹° ν‚€λ₯Ό λ§Œλ“€λ©΄ λ‹€λ₯Έ ν”„λ‘œνΌν‹° 킀와 μ ˆλŒ€ μΆ©λŒν•˜μ§€ μ•ŠλŠ”λ‹€.

μ‹¬λ²Œκ³Ό ν”„λ‘œνΌν‹° 은닉

  • μ‹¬λ²Œ 값을 ν”„λ‘œνΌν‹° ν‚€λ‘œ μ‚¬μš©ν•˜μ—¬ μƒμ„±ν•œ ν”„λ‘œνΌν‹°λŠ” for ... in λ¬Έμ΄λ‚˜ Object.keys, Object.getOwnPropertyNames λ©”μ„œλ“œλ‘œ 찾을 수 μ—†λ‹€.
  • 외뢀에 λ…ΈμΆœν•  ν•„μš”κ°€ μ—†λŠ” ν”„λ‘œνΌν‹°λ₯Ό μ‹¬λ²Œ ν”„λ‘œνΌν‹°λ₯Ό 톡해 은닉 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • ES6μ—μ„œ λ„μž…λœ Object.getOwnPropertySymbols λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μ‹¬λ²Œ 값을 ν”„λ‘œνΌν‹° ν‚€λ‘œ μ‚¬μš©ν•˜μ—¬ μƒμ„±ν•œ ν”„λ‘œνΌν‹°λ₯Ό 찾을 수 있음

μ‹¬λ²Œκ³Ό ν‘œμ€€ 빌트인 객체 ν™•μž₯

  • ν‘œμ€€ 빌트인 객체λ₯Ό ν™•μž₯ν•˜λŠ” 것은 이후 좔가될 λ©”μ„œλ“œμ˜ 이름과 쀑볡될 κ°€λŠ₯성이 μžˆμœΌλ―€λ‘œ ꢌμž₯ λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  • μ΄λ•Œ μ‹¬λ²Œ ν”„λ‘œνΌν‹° ν‚€λ₯Ό μƒμ„±ν•˜μ—¬ ν‘œμ€€ 빌트인 객체λ₯Ό ν™•μž₯ν•˜λ©΄ ν‘œμ€€ 빌트인 객체의 κΈ°μ‘΄ ν”„λ‘œνΌν‹° 킀와 μΆ©λŒν•˜μ§€ μ•ŠλŠ” 것은 λ¬Όλ‘ , 이후 좔가될 μ–΄λ–€ ν”„λ‘œνΌν‹° 킀와도 좩돌 μœ„ν—˜μ΄ μ—†μ–΄ μ•ˆμ „ν•˜κ²Œ ν‘œμ€€ 빌트인 객체λ₯Ό ν™•μž₯ κ°€λŠ₯ ν•©λ‹ˆλ‹€.
// μ‹¬λ²Œ κ°’μœΌλ‘œ ν”„λ‘œνΌν‹° ν‚€λ₯Ό 동적 μƒμ„±ν•˜λ©΄ λ‹€λ₯Έ ν”„λ‘œνΌν‹° 킀와 μ ˆλŒ€ μΆ©λŒν•˜μ§€ μ•Šμ•„ μ•ˆμ „ν•˜λ‹€.
Array.prototype[Symbol.for('sum')] = function () {
  return this.reduce((acc, cur) => acc + cur, 0);
};

[1, 2][Symbol.for('sum')](); // -> 3

Well-known Symbol

  • μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ κΈ°λ³Έ μ œκ³΅ν•˜λŠ” 빌트인 μ‹¬λ²Œ 값을 ECMAScript μ‚¬μ–‘μ—μ„œλŠ” Well-known Symbol이라고 λΆ€λ₯Έλ‹€.
  • Well-known Symbol 은 μžλ°”μŠ€ν¬λ¦½νŠΈ μ—”μ§„μ˜ λ‚΄λΆ€ μ•Œκ³ λ¦¬μ¦˜μ— μ‚¬μš©λœλ‹€.
  • 빌트인 μ‹¬λ²Œ 값은 Symbolν•¨μˆ˜μ˜ ν”„λ‘œνΌν‹°μ— ν• λ‹Ήλ˜μ–΄ μžˆλ‹€.
  • Array, String, map, set λ“± for ... of 문으둜 순회 κ°€λŠ₯ν•œ 빌트인 μ΄ν„°λŸ¬λΈ”μ€ Well-known Symbol인 Symbol.iteratorλ₯Ό ν‚€λ‘œ κ°–λŠ” λ©”μ„œλ“œλ₯Ό 가진닀.
  • Symbol.iterator λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μ΄ν„°λ ˆμ΄ν„°λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ ECMAScript 사양에 κ·œμ •λ˜μ–΄ μžˆλ‹€.
  • λ§Œμ•½ 일반 객체λ₯Ό μ΄ν„°λŸ¬λΈ” 처럼 λ™μž‘ν•˜λ„λ‘ κ΅¬ν˜„ν•˜κ³  μ‹Άλ‹€λ©΄ μ΄ν„°λ ˆμ΄μ…˜ ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜μ—¬ Symbol.iteratorλ₯Ό ν‚€λ‘œ κ°–λŠ” λ©”μ„œλ“œλ₯Ό κ°œμ²΄μ— μΆ”κ°€ν•˜κ³  μ΄ν„°λ ˆμ΄ν„°λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ κ΅¬ν˜„ν•˜λ©΄ 됨

이처럼 μ‹¬λ²Œμ€ μ€‘λ³΅λ˜μ§€ μ•ŠλŠ” μƒμˆ˜κ°’μ„ μƒμ„±ν•˜λŠ” 것은 λ¬Όλ‘  기쑴에 μž‘μ„±λœ μ½”λ“œμ— 영ν–₯을 주지 μ•Šκ³  μƒˆλ‘œμš΄ ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•˜κΈ° μœ„ν•΄, 즉 ν•˜μœ„ ν˜Έν™˜μ„±μ„ 보μž₯ν•˜κΈ° μœ„ν•΄ λ„μž…λ˜μ—ˆλ‹€.

λŒ“κΈ€