티스토리 뷰
ES5 까지의 자바스크립트의 원시 타입은 number, string, boolean, undefined, null, Object 뿐 이었습니다. 하지만 ES6에서 새로운 Symbol 타입이 소개되었습니다. 이 Symbol타입은 고유한 값을 만들어내기 위해 사용됩니다. 생성된 심볼을 변수에 담아놓지 않으면 접근이 불가능합니다. 또한, 객체의 key값으로 사용될 경우 private 멤버 변수 처럼 동작합니다. 자세한건 아래 내용을 살펴봅시다.
symbol의 특징
열거대상에서 제외
심볼을 객체의 키로 사용하게 되면 for .. in 문으로 순회가 불가능합니다. obj2에 있는 2개의 심볼은 콘솔에 찍히지 않았습니다. 왜그렇냐면, 생성된 심볼을 변수에 담아 놓아야만 나중에 그 변수를 통해서 심볼에 접근이 가능해집니다. 변수에 담기지 않은 심볼은 그 어디에서도 영원히 접근할 수 없습니다.
symbol은 고유한 값이다.
심볼은 그 자체로 고유한 값입니다. 안에 내용물이 같다고 해서 심볼이 같진 않습니다. 심볼은 한번 생성되면 절대 그 누구와도 같지 않습니다. 오직 본인과만 똑같은거죠.
toString() 처리
심볼로 전달된 매개변수(위에선 obj)가 string이 아닐 경우 toString()을 호출합니다.
property 은닉화
함수안에서 심볼을 정의하고 그 심볼을 객체 property의 key로 사용하고 있습니다. 이 심볼은 외부에서 직접 접근이 불가능한 private 멤버 변수가 되었습니다. 왜냐면 심볼은 변수를 통해서만 접근이 가능한데 그 변수를 객체에 넣지 않았으니까 외부에서는 심볼에 접근할 수 없겠죠?
그래서 y.a를 했을때 undefined가 출력되었습니다. Symbol('a')이 실행되는 순간 고유한 private uuid가 만들어진다고 생각하면 이해하기 수월한 것 같습니다.
아래처럼 해주면 심볼이 담긴 변수를 객체에 넣어주면 외부에서 접근이 가능해집니다.
심볼은 변수를 통해서만 접근 가능하다.
NAME과 GENDER라고 하는 심볼 두개를 만들었고 두개의 고유한 심볼을 myInfo 객체 내에서 key로 사용했습니다. 콘솔에 찍었을때는 심볼 2개와 age가 잘 노출되고 있습니다.
하지만, myInfo에 있는 두개의 심볼 NAME, GENDER는 콘솔에서 자동완성이 되지 않고 있습니다. 오로지 처음 심볼을 만들어줄때 할당했던 NAME 변수와 GENDER변수를 통해서만 심볼에 접근 할 수 있습니다.
만약에 아래와 같이 심볼을 생성할때 변수에 담아주지 않으면 생성된 심볼에 접근이 불가능해 집니다. 결국 obj에 있는 1과 2라는 값은 얻어올 수 없는 상태가 되었죠.
심볼을 사용할때는 무조건 변수에 먼저 담은 다음에 property의 key로 할당해야 합니다. 그래야 그 변수를 통해서 심볼을 가져올 수 있고 그 심볼을 통해 property의 value도 가져올 수 있게 됩니다.
private 변수와 public 변수 모두에 접근하고 싶을때
위 예제에서는 두개의 심볼을 생성하고 변수에 담지 않았습니다. 그럼 이 심볼은 영원히 다른곳에서 접근이 불가능한것 아니냐고 물어볼 수 있겠지만
사실은,
Reflect.ownKeys()를 사용하면 내부의 심볼을 가져올 수 있습니다.
Symbol을 만든 목적이 private한 멤버 변수를 만들기 위함이기 때문에 이런식으로 심볼을 가져오는건 어떻게 보면 hack이기 때문에 디버깅 용도로만 사용하길 권장합니다.
자바와 자바스크립트의 private 변수 비교
Java
class Test {
private name;
public setName(string name) {
this.name = name;
}
public getName(){
return name;
}
}
Javascript
const Test = (() => {
const _name = Symbol('이름');
const obj = {
[_name]: '심재철, 외부에서 보이긴 하지만 접근은 불가능함',
};
const setName = (name) => obj[_name] = name;
const getName = () => obj[_name];
return Object.assign({}, obj, {setName, getName});
})();
console.log(Test.getName()); // 심재철 출력
Test.setName('심심재');
console.log(Test.getName()); // 심심재 출력
자바스크립트에서는 즉시 실행 함수를 통해 private 멤버 변수 _name의 scope를 함수 내부로 가뒀습니다. 이제 이 _name이란 변수는 함수 내부에서만 접근이 가능하며 심볼로 정의되어 있기때문에 외부에서 직접적으로 수정이 불가능합니다. 따라서 함수 내의 getter와 setter를 통해서만 심볼을 사용해서 객체의 값을 수정하고 있는거죠.
'Javascript' 카테고리의 다른 글
es6의 Generator와 es7의 Async/Await (0) | 2020.05.14 |
---|---|
자바스크립트 애니메이션 - requestAnimationFrame 활용하기 (1) | 2020.03.31 |
#20-1 참조 투명성 예시 (referential transparency) (0) | 2019.09.26 |
#20 순수함수와 사이드 이펙트 (0) | 2019.09.26 |
#14-2 팩토리 패턴 vs 클래스 어떤것이 객체 생성에 더 좋은 방법일까? (0) | 2019.09.25 |
- Total
- Today
- Yesterday
- javascript
- react hooks
- Babel
- useRef
- return type
- reactdom
- atomic design
- computed
- props
- react
- Action
- server side rendering
- rendering scope
- promise
- state
- reflow
- type alias
- mobx
- hydrate
- Next.js
- await
- design system
- reducer
- Polyfill
- typescript
- async
- es6
- webpack
- useEffect
- storybook
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |