[ ECMA Script6 ]
(http://book.naver.com/bookdb/book_detail.nhn?bid=11556385)
symbol 오브젝트
1> ES6에서 추가 된 7번째 프리미티브(primitive, 원시형) 타입
symbol은 프리미티브 값으로 String, Number등의 다른 프리미티브 값과 같이 래퍼 오브젝트(Symbol)를 가지고 있습니다. 그리고 이 래퍼 오브젝트에는 프리미티브 값을 처리하기 위한 메서드와 프로퍼티가 존재합니다.
(참조 타입과 원시 타입 - http://codingnuri.com/javascript-tutorial/javascript-primitive-types-and-reference-types.html)
2> 프로그램 전체를 통해 유일한 값을 생성
3> symbol 값의 생성
const sym = Symbol([discription]);
Symbol값의 생성은 위의 형태로 작성하며 [discription]은 생성한 symbol에 대한 설명으로 선택적으로 사용합니다.
4> symbol 값의 출력
1 | const sym = Symbol('심볼'); |
symbol을 통해 생성된 값은 변경, 확인이 불가능합니다.
5> symbol 값의 변경
symbol값은 변경할 수 없습니다.
- 연산자로 문자를 연결하면 에러가 발생하며 템플릿에도 사용할 수 없습니다.
(단, String(), ToString()을 사용하여 문자열을 연결할 수는 있습니다.)
symbol 활용
1> 오브젝트에서 Symbol 사용
유일한 값을 갖는 symbol의 특성을 활용하여 symbol값을 오브젝트의 프로퍼티 키로 사용하면 중복되지 않는 프로퍼티 키가 되는 데 이러한 형태를 symbol-keyed property라고 하며 objectName[Symbol([discription])]의 형태로 작성합니다.1
2
3
4
5
6
7
8
9
10
11
12
13const sym = Symbol('123');
let obj = {
[sym]: '456'
};
console.log(sym); // Symbol(123)
console.log(obj[sym]); // '456'
console.log(obj.sym); // undefined
// symbol-keyed property 형태의 프로퍼티는 for-in문에서 열거되지 않음
for(let val in obj) {
console.log(value); // undefined
}
위의 예제에서 처럼 symbol-keyed property는 for-in문을 통해 열거되지 않습니다. ([[Enumerable]]:false 이기 때문이며 Object.getOwnProperty.Symbols()를 사용하여 열거할 수 있습니다.)
2> class의 method 이름으로 symbol 사용
1 | const symbolOne = Symbol('symbol one'); |
오브젝트에서와 마찬가지로 ClassNameSymbol([discription])의 형태로 사용합니다.
3> JSON.stringfy()에서 Symbol 사용
JSON.stringfy()를 실행하면 symbol-keyed property는 출력되지 않습니다. 이는 Symbol값을 외부에 노출되지 않도록 하기 위한 조치이며 불완전하지만 Object.getOwnPropertySymbols()를 사용하여 대처할 수 있습니다.1
2
3
4
5
6
7let sym = Symbol('key');
let obj = {
[sym]: 'value'
};
let result = JSON.stringfy(obj);
console.log(result);
symbol properties
1> well-known Symbol(표준심볼, 잘 알려진 심볼)
well-known Symbol은 스펙에서 처리 알고리즘을 구분하기 위해 부여한 이름으로 즉 JS 엔진이 디폴트로 퍼리하는 알고리즘 유형의 이름 입니다.(처음부터 시스템에 존재하는(엔진이 가지고 있는) 상수형태의 심볼)
스펙에서는 Symbol.iterator가 아닌 @@interator로 작성되어 있는 데 이것은 즉 @@ == Symbol 입니다.
프로그램에 같은 이름의 well-Known symbol을 작성하면 엔진의 디폴트 처리를 하지 않고 작성된 코드를 실행합니다(well-known symbol이 오버라이드 되는 것)
표준 심볼(Well-known Symbol)로써 사용
ES6가 등장하기 전에 사람들의 필요에 의해 생성하거나 개발한 함수들이 많을 것이다.
그 중에 공통된 함수들은 기능과 네이밍이 비슷한 경우가 많을 것이다. (내부 로직은 다를지라도)
이렇게 많은 사람들이 쓴 함수의 이름 등등을 표준 프로퍼티로 만들고 나면?
내부 로직이 다 같지는 않으므로 그 수많은 코드가 깨질 수 있다. (우리 Array.isArray와 마찬가지로 말이다.)
따라서 기존 개발자들이 개발한 코드들의 안전성을 보장하고자 표준 프로퍼티를 심볼로 만든 경우가 있다.
그 목록은 아래와 같다.
Symbol.iterator(추후 다룰 예정)
Symbol.unscopables
Symbol.match
Symbol.species
Symbol.toPrimitive
등등…
출처 (https://perfectacle.github.io/2017/04/16/ES6-Symbol/)
2> toStringTag
[object Object] 형태에서 ‘Object’를 symbol.toStringTag 값으로 표시 합니다.1
2
3
4
5
6
7let Sports = function(){};
let sportsObj = new Sports();
console.log(sportsObj.toString()); // [object Object]
Sports.prototype[Symbol.toStringTag] = 'Sports-Function';
console.log(sportsObj.toString()); // [object-Sports-Function]
아래 예제와 같이 class에서의 getter로도 작성할 수 있습니다.1
2
3
4
5
6
7
8class Sports{
get [Symbol.toStringTag]() {
return 'Sports-Function'
}
};
let sportsObj = new Sports();
console.log(sportsObj.toString());
3> isConcatSpreadable
Array 오브젝트의 concat()에서 배열을 결합할 때 결합하는 배열의 펼침 여부를 지정
(concat()은 인자로 주어진 배열이나 값들을 기존배열에 합쳐서 새 배열로 반환하는 메서드 - https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/concat)
Symbol.isConcatSpreadable = Boolean(기본 값은 true)
1 | let one = [11, 12]; |
isConcatSpreadable의 프로퍼티로만 사용할 수 있고 함수로 사용할 수 없으며 Array-like 오브젝트 및 상속받은 class에 사용할 수 있습니다.
Array-like에서의 사용 예1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19let one = [11, 12];
let fiveSix = {
0: 'five',
1: 'six',
length: 2
};
let result = one.concat(fiveSix);
// Array-like에서 isConcatSpreadable의 값은 기본이 false인 듯
console.log(result, result.length);
let arrayLike = {
[Symbol.isConcatSpreadable]: true,
0: 'five',
1: 'six',
length: 2
};
result = one.concat(arrayLike);
console.log(result, result.length);
4> unscopables
with문에서 사용되며 값이 true라면 프로퍼티를 전개하지 않습니다.(with문의 사용을 권장하지 않는 내용도 있으니 참고 - http://unikys.tistory.com/304)
Symbol.unscopables = Boolean(기본 값은 false)
ES5의 ‘use strict’ 범위와 ES6환경에서는 with문을 사용하면 에러가 발생합니다.
(Uncaught SyntaxError: Strict mode code may not include a with statement)
5> species
Symbol.species는 constructor를 반환합니다.
(여기서 constructor를 반환한다는 것은 constructor로 인스턴스를 생성하여 반환하는 것과 같은 이야기)
Symbol.species는 오버라이드 할 수 있으며 개발자 코드로 변환되는 인스턴스를 변경할 수 있습니다.
1 | class ExtendArray extends Array { |
symbol.for
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for