티스토리 뷰
ES6에서 number, boolean, string, undefined, null, object 이외에 7번째 새로운 자료 구조인 Symbol이 등장했다.
Symbol
심볼은 unique id를 생성해주는 factory 함수라고 생각하면 편하다.
let symbol2 = Symbol('simsimjae');
이런식으로 simsimjae라고 하는 이름을 가진 심볼을 생성할 수 있다. 여기서 'simsimjae'의 역할은 심볼에 이름을 붙인거(description)라고 생각하면 된다. 따라서 같은 이름을 가진 심볼을 2개를 만들었다고 해서 그 두개의 심볼이 같은것은 아니다.
Symbol('simsimjae') !== Symbol('simsimjae')
왜냐면 심볼은 생성할때마다 유니크한 값이 되기 때문이다.
Symbol의 사용처
객체의 property key로 사용된다.
const SymbolPropertyKey = Symbol();
let obj = {};
obj[SymbolPropertyKey] = 123;
console.log(obj[SymbolPropertyKey]); // 123
좀 더 간단하게는 이렇게 사용할 수 있다.
const SymbolPropertyKey = Symbol();
let obj = {
[SymbolPropertyKey]: 123
};
좀 더 간단하게는 이렇게 사용할 수 있다.
let obj = {
[Symbol('SymbolPropertyKey')]: 123
};
이런식으로 객체의 메소드를 가리킬수도 있다.
const FOO = Symbol();
let obj = {
[FOO]() {
return 'bar';
}
};
console.log(obj[FOO]()); // bar
FOO라는 심볼(unique한 string값이라고 생각하자.) 메소드를 선언했다.
객체의 키로 string을 사용하게 되면 이런 문제가 발생할 수 있다.
const obj = {
'hello': 'world',
'hello': 'here'
};
나중에 나온 hello key가 그 위에서 선언된 key를 덮어 씌워서
console.log(obj.hello) // "here"를 출력함
이렇게 된다.
그래서 객체의 키로 심볼을 사용하게 될 경우 description이 똑같다 하더라도 매번 고유한 값이 생성되기 때문에 property key가 충돌되지 않을거라고 확신할 수 있다. 심볼은 이런 이름 충돌에 대한 니즈 때문에 탄생하게 되었다.
own property key를 열거하는 방법
ES5까지는 객체의 키로 무조건 string만 사용할 수 있었지만 ES6에서는 심볼을 객체의 키로 사용할 수 있도록 추가되었다. 애초에 심볼의 탄생 목적이 객체의 property key를 unique하게 만들기 위한 목적이라고 한다.
let obj = {
[Symbol('my_key')]: 1,
enum: 2,
nonEnum: 3
};
symbol은 열거가능하지 않다. 여기서 열거의 의미는 for .. in 문이나 object spread에서 확인이 가능한 값이냐는 소리다.
따라서, 만약 아래와 같이
Object.keys(obj)
['enum', 'nonEnum'] 출력
Object.keys를 사용해서 객체의 모든 키를 배열로 만들어도 Symbol은 노출이 되지 않는다. Symbol은 enumerable(열거가능)하지 않기 때문이다.
만약 obj의 nonEnum property도 non enumerable로 만들고 싶으면 아래와 같이 하면 된다.
Object.defineProperty(obj,
'nonEnum', { enumerable: false });
한번 더 Object.keys를 호출해보면
Object.keys(obj)
['enum'] 출력
enum만 출력된다.
객체 내부의 property들을 확인하는 3가지 방법
ES6에서는 객체의 키로 string or Symbol 두가지가 가능하다고 했다. 따라서, 키가 string이냐 Symbol이냐에 따라서 호출해야 하는 함수가 달라진다.
Object.getOwnPropertyNames(obj)
이 함수를 호출하면 객체의 key가 string인것들만 출력해준다. (enum, nonEnum출력)
Object.getOwnPropertySymbols(obj)
이 함수를 호출하면 객체의 key가 Symbol인것들만 출력해준다. ( [Symbol(my_key)] 출력)
만약 key가 Symbol이냐 string이냐에 상관없이 모든 property를 출력하고 싶을땐
Reflect.ownKeys(obj)
[Symbol(my_key), 'enum', 'nonEnum']
이렇게 해주면 된다. Reflect란 (거울) '비추다' 라는 뜻이다. 한마디로 객체 내부를 비춰 뭐가 있는지 확인한다고 생각하면 편하다.
Symbol의 scope
심볼은 우리가 흔히 global scope라고 부르는 것(브라우저에서는 window객체)보다 더 global하다. 아이프레임을 사용해본적이 있는 개발자들은 아이프레임의 scope와 현재 scope가 다르다는것을 알것이다.
function test(arr) {
var iframe = frames[0];
// 아이프레임의 Scope와 현재 javascript의 global Scope는 다르다.
console.log(Array === iframe.Array); // false
console.log(arr instanceof Array); // false, arr은 iframe에서 전달한 배열
console.log(arr instanceof iframe.Array); // true
// 그러나 심볼은 아이프레임과도 scope를 공유한다.
console.log(Symbol.iterator === iframe.Symbol.iterator); // true
}
그래서 우리가 기존에 알고 있던 global은 사실 진짜 global이 아니다. 현재 자바스크립트가 동작하고 있는 호스트 환경(브라우저, 노드)에 따라 global은 얼마든지 변경될 수 있다. 진짜 global한 값을 만들고 싶으면 심볼을 사용해야 한다.
global symbol의 위치
자바스크립트 엔진에는 Symbol registry라고 하는것이 존재한다.
string : Symbol의 entry로 이루어진 map이라고 생각하면 되는데 엔진에 존재하기 때문에 진짜 global한 값을 만들 수 있다.
이곳에 어떤 심볼을 집어 넣어 두면 모든 영역에서 유일한 값을 저장해놓고 쓸 수 있다.
그렇게 하기 위해서는 아래 메소드를 사용 해야 한다.
let sym = Symbol.for('Hello everybody!'); // Symbol registry에 유니크한 공유 심볼 생성
이 Symbol.for 메소드는 symbol registry에서 Hello everybody!라는 string이 있는지 없는지 찾아본다음에 있으면 그걸 리턴해주고 없으면 새로 만들어주는 메소드이다.
그냥 한마디로 global registry를 찾아보는 메소드라고 생각하자.
Symbol.keyFor(sym)
'Javascript' 카테고리의 다른 글
Class에서 arrow function을 사용하지 말아야하는 이유 (3) | 2020.06.30 |
---|---|
how to detect element size change in javascript (0) | 2020.06.15 |
ES6의 Bare Import란? (1) | 2020.06.09 |
async 키워드 (0) | 2020.05.14 |
함수가 AsyncFunction인지 알아보는 방법 (0) | 2020.05.14 |
- Total
- Today
- Yesterday
- reducer
- async
- server side rendering
- return type
- typescript
- useEffect
- reactdom
- atomic design
- promise
- react hooks
- type alias
- rendering scope
- javascript
- state
- storybook
- Polyfill
- mobx
- hydrate
- Action
- useRef
- es6
- reflow
- webpack
- Next.js
- computed
- Babel
- props
- await
- react
- design system
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |