PracticeEveryday

JavaScript 본문

JavaScript

JavaScript

kimddakki 2022. 5. 12. 16:39
Symbol Data Type

ECMAScript로 표준화된 이후로 자바스크립트에는 string, number, boolean, null, undefined, object 6개의 데이터 타입 있었다.  + es6에서 새로운 데이터 타입 Symbol이 추가 되었다. 

 

Symbol심볼은 변경 불가능한 원시 타입의 값이며, 다른 값과 중복되지 않는 고유한 값이다. 심볼 값은 충돌 위험이 없는 오브젝트의 유일한 프로퍼티 키를 만들기 위해 사용할 수 있다.하위 호환성을 유지하면서 표준을 확장한다든지, 고유한 상수값을 만드는 데 사용할 수 있다.

 

const symbolA = Symbol("symbol");
const symbolB = Symbol("symbol");
console.log(symbolA, symbolB); // Symbol(symbol), Symbol(symbol)

console.log(symbolA === symbolB); // false

 


Symbol 함수

Symbol값은 Symbol 함수를 호출하여 생성한다.

심볼 값은 자바스크립트 런타임 환경에서 Symbol 함수에 의해 동적으로 생성되며 다른 값과 중복되지 않는 고유한 값이며 심볼 값은 외부로 노출되지 않아 확인 할 수 없다!!

 

 

const a = Symbol("a");
console.log(a); // Symbol(a)
console.log(a.description); // a
console.log(a.toString()); // Symble(a)
console.log(!a); // false
// console.log(a + "hi"); Error

console.log(a.__proto__); // Object [Symbol] {}
console.log(a.prototype); // undefined not 함수

const sym1 = Symbol();
const sym2 = Symbol("foo");
const sym3 = Symbol("bar");

console.log(sym1); // Symbol()
console.log(sym2); // Symbol(foo)
console.log(sym3); // Symbol(bar)

console.log(typeof sym1); // symbol
console.log(typeof sym2); // symbol
console.log(typeof sym3); // symbol

const sym4 = Symbol("foo");

console.log(sym1 === sym1); // true

console.log(sym1 === sym2); // false
console.log(sym3 === sym4); // false

// Symbol 함수를 호출하면 매번 새로운(고유한) 심볼이 생성된다!!

 

Symbol 함수에 들어가는 문자열 인자는 심볼 값에 대한 description으로서 선택적으로 넣을 수 있다.

Symbol 함수를 호출 할 때 인자로 전달되는 문자열 값은 심볼에 대한 일종의 설명문(Description))으로이 문자열은 디버깅 용도로만 사용되며 심볼 값 생성에 영향을 주지는 않는다.

 

// Symbol Key값과는 완전히 다른 것으로 console.log() 등을 이용한 디버깅 시에 각 심볼을 구분하기 위한 용도로 사용된다!!

 

심볼 값도 객체처럼 메서드를 사용하면 암묵적으로 *래퍼 객체를 생성한다. description 프로퍼티와 toString은 Symbol.prototype의 프로퍼티다. 심볼 값은 문자열이나 숫자 타입으로 변환되지 않는다. 단 불리언 타입으로는 타입 변환이 된다.

 

Symbol type은 어디에 쓰일까

 - 일반적을 심볼은 객체의 프로퍼티 키(해당 프로퍼티의 값에 접글 할때 사용하는 이름)로 사용된다.

 - JavaScript 객체의 프로퍼티 키는 대개 문자열 값이다. (숫자또한 내부적으로 문자열로 변환된다! )

 

const obj = {};

obj.propertyKey1 = "propertyValue1";
obj["propertyKey2"] = "propertyValue2";

obj[3] = "propertyvalue3";
console.log(obj);
/**
 * {
 *  '3': 'propertyvalue3', 
 *  propertyKey1: 'propertyValue1', 
 *  propertyKey2: 'propertyValue2' 
}
 */

const obj2 = {};

const sym5 = Symbol();
const sym6 = Symbol("foo");
const sym7 = Symbol("foo");

obj2[sym5] = "propertyValue1";
obj2[sym6] = "propertyValue2";
obj2[sym7] = "propertyValue3"; // no conflict with sym6

console.log(obj2); // {Symbol(): 'propertyValue1', Symbol(foo): 'propertyValue2', Symbol(foo): 'propertyValue3'}

console.log(obj2[sym5]); // propertyValue1
console.log(obj2[sym6]); // propertyValue2
console.log(obj2[sym7]); // propertyValue3

 


전역 심볼 레지스트리, global symbol registry

Symbol 함수를 호출함으로써 생성하는 심볼들은 키를 가지고 있지 않으며, 전역 심볼 레지스트리에 저장되지도 않는다. 

전역 심볼 레지스트리(Global Symbol Registry)란 심볼들이 저장되는 전역 공간을 의미하는 것이며, 여러 모듈들이 하나의 심볼을 공유하기 위한 용도로 존재한다.

여러 모듈들이 하나의 심볼을 공유하려면 그 심볼이 를 가지고 있어야 한다. 그래야 키를 통해 이미 존재하는 심볼을 찾아 재활용할 수 있기 때문이다.

 

const symA = Symbol.for("a");
const symB = Symbol.for("a");

console.log(symA === symB); // true
console.log(Symbol.keyFor(symA)); // a
console.log(Symbol.keyFor(symB)); // a

const unsharedSym = Symbol("foo");
const symKey1 = Symbol.keyFor(unsharedSym);
console.log(symKey1); // undefined

const sharedSym = Symbol.for("foo");
const symKey2 = Symbol.keyFor(sharedSym);
console.log(symKey2); // foo

Symbol.for 메서드는 인수로 전달받은 문자열을 키로 사용해 전역 심볼 레지스트리에 해당 키와 일치하는 심볼 값을 검색한다. 레지스트리에 이미 심볼이 있으면 해당 심볼을 반환하고, 없으면 새로 생성하여 반환한다.

 

Symbol.keyFor 메서드는 심볼 값을 인수로 받아서 전역 심볼 레지스트리에 저장된 심볼 값 키를 가져올 수 있다.

 

Symbol 함수는 호출될 때마다 심볼 값을 생성하지만, 전역 심볼 레지스트리에서 관리할 때 필요한 키를 지정할 수 없으므로(인수로 전달하는 문자열 키는 description일 뿐이다)

전역 심볼 레지스트리에 등록되어 관리되지 않는다. 그러나 Symbol.for 메서드를 사용하면 문자열 키를 통해 전역에서 중복되지 않는 유일무이한 심볼 값을 하나만 생성하여, 전역 심볼 레지스트리를 통해 값을 공유할 수 있다.


for ... in 문법과 JSON.stringify() 메소드의 심볼

심볼은 객체의 property의 키로 사용되지만 JavaScript가 제공하는 for ... in 문법에는 심볼을 키로 사용하는 프로퍼티들은 열거가 되지 않는다.  +  Object.getOwnPropertyNames() 메소드 또한 심볼이 키인 프로퍼티들을 반환하지 않는다.

const obj3 = {};

obj3[Symbol("a")] = "a";
obj3[Symbol.for("b")] = "b";
obj3["c"] = "c";
obj3.d = "d";

for (const propertyKey in obj3) {
  console.log(propertyKey); // logs 'c' and 'd'
}

console.log(Object.getOwnPropertyNames(obj3)); //['c', 'd']
console.log(Object.getOwnPropertySymbols(obj3)); // [Symbol(a), Symbol(b)]

 

또한 객체를 JSON으로 만들 때 키가 심볼인 프로퍼티들을 무시된다!!

 

const sym = Symbol("foo");
const obj4 = {
  [sym]: "propertyValue1",
  propertyKey2: "propertyValue2",
};

console.log(JSON.stringify(obj4)); // {"propertyKey2":"propertyValue2"}

Symbol method를 사용하면 전역 Symbol 레지스트리에 들어가지 않는다!!

Symbol Object의 for method를 사용하면 전역 Symbol 레지스트리 Symbol이 생성되어

이 후 Symbol.for 메서드를 사용하면 전역 레지스트리 내의 심볼 값을 내준다. (없다면 새로 생성 한 후 반환해 준다)

심볼은 고유한값이다!!

const a = Symbol("a");
console.log(a); // Symbol(a)
console.log(a.description); // a

const b = Symbol.for("b");
console.log(b); // Symbol(b)
console.log(b.description); // b
console.log(Symbol.keyFor(b)); // b

const c = Symbol.for("b");
console.log(b === c); // true
console.log(a === c); // false

console.log(Symbol.keyFor(a)); // undefined

 

 

[JavaScript] 심볼 (Symbol) 타입 이해하기

JavaScript는 총 6개의 원시 타입(Number, String, Boolean, null, undefined, Symbol)과 1개의 객체 타입(Object)을 가지고 있다. 이번 포스팅에서 다룰 심볼(Symbol) 타입도 6개의 원시 타입 중 하나로, ES6 버..

it-eldorado.tistory.com

 

'JavaScript' 카테고리의 다른 글

JavaScript  (0) 2022.05.13
JavaScript  (0) 2022.05.12
JavaScript  (0) 2022.05.12
JavaScript  (0) 2022.05.10
JavaScript  (0) 2022.05.10
Comments