Symbol
자바스크립트에서는 총 6개의 타입이 있었습니다. 문자열, 숫자, 불리언, undefined, null 그리고 객체 타입이 존재했습니다. ES6 에서는 7 번째 데이터 타입인 심벌(Symbol)이 등장합니다. 심벌은 원시값으로 다른 값과 절대로 중복되지 않는 유일무이한 값을 만들어냅니다. 주로 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해서 사용하는 심벌에 대해서 정리해보도록 하겠습니다.
Symbol 함수로 Symbol 만들기
심벌 값은 Symbol 함수를 호출해서 생성합니다. Symbol 은 리터럴 표기법을 통해서 생성할 수 없고 new 연산자와 함께 호출이 불가능합니다.
// Symbol 함수를 호출하여 유일무이한 심벌 값을 생성한다.
const mySymbol = Symbol();
console.log(typeof mySymbol); // symbol
// 심벌 값은 외부로 노출되지 않아 확인할 수 없다.
console.log(mySymbol); // Symbol()
// Symbol 함수는 new 연산자와 호출하지 않는다.
new Symbol(); // TypeError: Symbol is not a constructor
Symbol 함수에는 문자열을 인수로 전달하는 것이 가능합니다. 이는 단순 설명, 디버깅 용도로만 사용되므로 심벌 값 생성에 어떠한 영향도 주지 않습니다. 만약 심벌 값에 대한 설명이 같다고 해도 심벌 값은 유일무이합니다.
// 심벌 값에 대한 설명이 같더라도 유일무이한 심벌 값을 생성한다.
const mySymbol1 = Symbol('mySymbol');
const mySymbol2 = Symbol('mySymbol');
console.log(mySymbol1 === mySymbol2); // false
Symbol.for, Symbol.keyFor
Symbol.for 메서드는 인수로 문자열을 전달 받습니다. 이를 키로 사용해 키와 심벌 값의 쌍들이 저장되어 있는 전역 심벌 레지스트리에서 키를 통해 심벌 값을 검색합니다.
1. 심벌 값이 존재하면 검색된 심벌 값을 반환합니다.
2. 실패하면 새로운 심벌 값을 생성하고 Symbol.for 에 인수로 전달된 키를 통해 전역 심벌 레지스트리에 저장하고 값을 반환합니다.
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값을 생성
const s1 = Symbol.for('mySymbol');
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 있으면 해당 심벌 값을 반환
const s2 = Symbol.for('mySymbol');
console.log(s1 === s2); // true
Symbol 함수와 Symbol.for 은 다르네요?
Symbol 함수는 유일무이한 심벌 값을 생성합니다. 전역 심벌 레지스트리는 키와 값의 쌍들이 저장되어 있다고 했습니다. Symbol 함수는 오직 설명과 디버깅을 위한 문자열을 인수로 전달 받아 키를 생성하지 않습니다. 즉, 전역 심벌 레지스트리에 등록되지 않습니다.
하지만 Symbol.for 은 키를 지정하므로 전역 심벌 레지스트리를 통해서 공유가 가능합니다. 이때 Symbol.keyFor 메서드를 통해서 전역 심벌 레지스트리에 저장된 심벌 값의 키 추출이 가능합니다.
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값을 생성
const s1 = Symbol.for('mySymbol');
// 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출
Symbol.keyFor(s1); // -> mySymbol
// Symbol 함수를 호출하여 생성한 심벌 값은 전역 심벌 레지스트리에 등록되어 관리되지 않는다.
const s2 = Symbol('foo');
// 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출
Symbol.keyFor(s2); // -> undefined
Symbol 을 통해 표준 빌트인 객체 확장하기
권장하지는 않지만, 표준 빌트인 객체에 사용자 정의 메서드를 직접 추가하여 확장하는 경우가 있을 수도 있습니다. 이때 개발자가 직접 추가한 메서드의 이름이 겹칠수도 있습니다. 실제로 Array.prototype.find 메서드는 ES6 에서 도입된 사양입니다.
하지만 이전에 사용자 정의 메서드를 통해서 추가하고 확장했다면, ES6 에서 추가된 후에는 기존 메서드가 추가된 메서드를 덮어 씌워버리는 문제가 발생합니다. 이때 중복될 가능성이 없는 심볼 값을 통해서 프로퍼티 키를 생성하면 표준 빌트인 객체 확장시에 키 충돌 문제를 해결해 안전한 확장이 가능합니다.
// 심벌 값으로 프로퍼티 키를 동적 생성하면 다른 프로퍼티 키와 절대 충돌하지 않아 안전하다.
Array.prototype[Symbol.for('sum')] = function () {
return this.reduce((acc, cur) => acc + cur, 0);
};
[1, 2][Symbol.for('sum')](); // -> 3
Symbol 은 이터러블을 배우기 위한 다리 역할입니다.
다음 글을 통해 알아볼 이터러블을 알기 위해서는 Symbol.iterator 에 대해서 알아야합니다. Symbol.iterator 를 키로 가지게 되면 유일무이한 프로퍼티키를 가지는 것이 가능하다는 것만 기억하고 다음 글에서 좀 더 자세히 알아보도록 하겠습니다.
Symbol 을 사용하면 기존에 작성된 코드에 영향을 주지 않고도 새로운 프로퍼티를 추가하는 것이 가능합니다. 즉, 이는 하위 호환성을 보장하기 위해서 도입됬다고도 할 수 있습니다.
보다 더 자세한 내용은 아래 링크에서 확인 가능하고, 저 또한 내용들을 공부하며 정리하기 위한 목적으로 글을 남기는 것을 알려드립니다. 읽어주셔서 감사합니다!
'자바스크립트 > 자바스크립트 정리' 카테고리의 다른 글
[자바스크립트] 스프레드 문법 (0) | 2021.06.06 |
---|---|
[자바스크립트] 이터러블 (0) | 2021.06.06 |
[자바스크립트] 배열의 메서드들 (0) | 2021.06.02 |
[자바스크립트] 배열 (0) | 2021.06.02 |
[자바스크립트] 정렬 구현해보기 (0) | 2021.06.01 |