Symbol
이란?
- ES2015 에서 추가된 7번째 타입으로 원시 데이터 타입(primitive data type)이다.
- 전까지는
Boolean
,null
,undefined
,Number
,String
,Object
가 있었다.
- 전까지는
- 익명의 오브젝트 프로퍼티를 만드는데 이용된다.
- 이름 충돌이 없는 유일한 객체 프로퍼티를 만든다.
- 프로퍼티를 의도치 않은 노출로부터 보호한다.
- 자바스크립트 빌트인 객체에 이미 많이 쓰이고 있다.
- 이는 심볼을 이용해 빌트인 객체를 확장해서 쓰라는 의도도 있다.
Symbol
추가가 갖는 의의
왜 굳이 고유한 객체의 키값이 필요할까? 문자열로 하면 안되는 걸까?
- 자바스크립트 언어 스펙을 정하는 사람들은 새로운 속성이나 메서드를 추가할 때 "다른 개발자들이 이미 쓰고있는 이름은 아닐까?" 하는 고민을 많이 했다.
- 문자열 키는 잘못 사용하면 이미 있는 키에 값을 덮어씌울 수도 있다는 단점을 가지고 있다.
Symbol
을 이용하면, 다른 개발자들이 해당 키를 사용하는지 걱정하지 않고 마음껏 새로운 기능을 추가할 수 있다.Symbol
은Object.keys()
와 같은 메서드로 열거되지도 않기 때문에, 기존의 하위 호환성을 지키기 좋다.
Symbol
을 통해 규약을 만들고 활용할 수도 있다.- 일례로 Well-known Symbols 라는 것이 있다.
- 이는 특별한 규약이 적용된 심볼들이라고 보면 된다.
Well-known Symbols
의getter
메서드를 오버라이드하면, 규약에 따른 기존 기능을 변경할 수 있다.- ex)
Symbol.toPrimitive
심볼 메서드를 오버라이드하면, 객체를 프리미티브 타입으로 변환할 때 어떠한 형태로 변할지를 오버라이드 할 수 있다. - ex)
Symbol.toSpecies
심볼 메서드를 오버라이드하면, 빌트인 메서드의 결과로 반환되는 타입을 오버라이드 할 수 있다.
- ex)
기본 사용 예제
var myPrivateMethod = Symbol();
this[myPrivateMethod] = function() {...};
- 심볼로 작성한 키는 비 열거형이라 일반적인 방법으로 접근 불가능하며, 보통
myPrivateMethod
심볼을 통해서 접근한다. Object.getOwnPropertySymbols()
이 반환하는 배열을 반복하여 접근하는 것도 가능하다.
심볼의 특징 1: 절대 동치가 되지 않는다.
var symbol1 = Symbol("S");
var symbol2 = Symbol("S");
console.log(symbol1 === symbol2); // false
- 두 심볼은 동치가 되지 않는다.
Symbol()
에 인자로 들어가는 문자열은 심볼에 대한 설명을 위해 디버깅 용도로 들어가는 것이지 심볼의 아이덴티티를 결정하지는 않는다.- 인자로 똑같이
"S"
가 들어갔다고 해서 같은 심볼이 되지 않는다.
- 이러한 이유로
Symbol
값을 키로 갖는 프로퍼티는 다른 어떠한 프로퍼티와도 충돌하지 않는다. - 심볼을 만든 뒤에 한번 참조를 놓치면 그 심볼은 영영 다시 가져올 수 없는 것이다.
심볼의 특징 2: Symbol
은 new
키워드로 생성이 불가능하다.
Symbol()
이 새로운 심볼을 생성하는 유일한 방법이다.- 혼동을 막기 위해
new Symbol()
등은 막아두었다.
심볼의 특징 4: 심볼은 정보 은닉을 위한 것이 아니다.
Symbol
을 키로 쓰는 프로퍼티는Object.getOwnPropertySymbols()
메서드를 통해 가져올 수 있다.- 키로 사용되는 심볼을 배열 형태로 가져온다.
- 속성에 대한 정보 은닉은 제공하지 않는다.
const mySymbol = Symbol("MySymbol");
const obj = {
[mySymbol]: "It is my symbol.",
};
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(MySymbol)]
심볼 테이블을 통해 심볼 만들기
- 특정한 심볼을 꺼내쓰기 위해 전역 심볼 테이블이라는 것이 존재한다.
Symbol
은.for()
와.keyFor()
와 같은 메서드를 갖는다.- 이는 전역 심볼 테이블(혹은 레지스트리)과 런타임 환경 사이를 중재한다.
- 전역 심볼 레지스트리(혹은 전역 심볼 테이블)는 자바스크립트 컴파일러의 인프라스트럭쳐에 의해 구축된다.
- 심볼 레지스트리의 내용은 리플렉티브 메서드를 통하지 않고 접근이 불가능하다.
Symbol.for()
: 전역 심볼 레지스트리에서 심볼 가져오기
const symbol_1 = Symbol.for("ABC"); // Symbol(ABC)
console.log(symbol_1 === Symbol.for("ABC")); // true;
- 전역 심볼 레지스트리로부터 심볼 값을 반환한다.
- 전역 심볼 레지스트리에서 가져온 심볼에는 키라는것이 존재하여, 동치인 심볼을 가져올 수도 있다.
- 단순히
Symbol()
을 통해 생성된 심볼은 키가 없어 동치인 심볼을 한번 더 생성하는 것이 불가능하다.
- 단순히
Symbol.keyFor()
: 심볼의 키 가져오기
const symbol1 = Symbol("S");
console.log(Symbol.keyFor(symbol1)); // undefined
const symbol2 = Symbol.for("ABC");
console.log(Symbol.keyFor(symbol2)); // 'ABC'
- 심볼은 동치 판단을 위해
key
를 가질 수 있다. Symbol()
생성자를 통해 만든 심볼은key
가 없다.- 전역 심볼 레지스트리에서 가져오는 심볼은
key
가 있다. Symbol.keyFor()
메서드는 심볼로부터 키(토큰 문자열)를 반환한다.Symbol()
을 통해 생성된 심볼인symbol1
은 위에서 말했듯 키가 없으므로undefined
가 반환된다.Symbol.for()
를 통해 생성된 심볼인symbol2
는 위에서 말했듯 키가 있으므로ABC
가 반환된다.
잘 알려진 심볼 (Well-Known Symbol)
- Well-Known Symbol 이란, 자바스크립트 엔진에 상수로 존재하는 심볼이다.
- 처음에도 설명했듯, 특정한 규약을 따르기 위한 목적으로 만들어진 심볼이다.
- 어떤 오브젝트가
Symbol.iterator
를 키로 한 메서드를 가지고 있다면, 자바스크립트 엔진은 이 오브젝트가 이터레이션 프로토콜을 따른다고 본다는 식이다.
Symbol.iterator
심볼 이용해보기
Array.prototype[Symbol.iterator]; // ƒ values() { [native code] }
Array
빌트인 객체의 프로토타입 객체의Symbol.iterator
에 접근하면,iterator
를 반환한다.
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
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}
console.log(arr instanceof Array); // true;
- 반환된
iterator
를 이용해보았다.
Symbol.toStringTag
오버라이드 해보기
class Example1 {}
class Example2 {
get [Symbol.toStringTag]() {
return "Example2";
}
}
const example1 = new Example1();
const example2 = new Example2();
console.log(example1.toString()); // [object Object]
console.log(example2.toString()); // [object Example2]
Symbol.toStringTag
getter
를 오버라이드하면 이름처럼toString()
메서드를 통해 나오는 값이 오버라이드된다.- 이렇게 오버라이드가 가능한 이유는
Object.prototype.toString()
메서드 구현이Symbol.toStringTag
의getter
반환 값을 이용하기 때문이다.- 자바스크립트 빌트인 객체는 이렇게
Well-known Symbol
규약을 잘 지키고 있기 때문에 개발자는 오버라이드하여 기능을 확장하기 좋다.
- 자바스크립트 빌트인 객체는 이렇게
레퍼런스
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Symbol
https://poiemaweb.com/es6-symbol#:~:text=%EC%8B%AC%EB%B3%BC(symbol)%EC%9D%80%20ES6%EC%97%90%EC%84%9C,%EB%A5%BC%20%EB%A7%8C%EB%93%A4%EA%B8%B0%20%EC%9C%84%ED%95%B4%20%EC%82%AC%EC%9A%A9%ED%95%9C%EB%8B%A4.
반응형
'자바스크립트 > 모던 자바스크립트' 카테고리의 다른 글
ES6 이후에 새롭게 정의된 Object 편의 정적 메서드들 (0) | 2023.01.30 |
---|---|
모던 자바스크립트, 메서드 정의 문법과 super, [[HomeObject]] (0) | 2023.01.25 |
모던 자바스크립트, 단축 속성 (shorthand properties) (0) | 2023.01.24 |
모던 자바스크립트, 계산된 속성 이름 (computed property name) (0) | 2023.01.24 |
모던 자바스크립트, 프로토타입 얻기 설정하기 (getPrototypeOf, setPrototypeOf) (0) | 2023.01.24 |