[JavaScript] Symbol

Narcoker·2022년 8월 24일
0

JavaScript

목록 보기
9/55

일반적인 Property

일반적으로 객체의 키 값은 문자형이다.

const obj = {
  1: '1입니다.',
  false : '거짓'
}
Object.keys(obj); // ["1", "object"]
obj['1']; // "1입니다."
obj['false']; // '거짓'

Symbol

프로그램 전체를 에서 유알한 값을 생성하여 반환한다.

  • 반환된 값을 볼 수 없다.
  • new 사용할 수 없다. -> constructor 가 없다.
  • 연산이 불가능하다. -> 심볼 내부값 유추가 가능해지기 때문
  • 타입 캐스팅이 불가능하다. -> 심볼 내부값 유추가 가능해지기 때문
  • ${Symbol()} 처럼 템플릿 리터럴 내부에 사용할 수 없다. -> 심볼 내부값 유추가 가능해지기 때문

객체의 키 값으로 가능한 것이 Symbol 형이다.
Symbol은 유일한 식별자를 만들 때 사용한다.

const a = Symbol();
const b = Symbol();
console.log(a); // Symbol();
console.log(b); // Symbol();
a === b; // false;
a == b; // false; 
// 자료형이 다르더라도 내용이 같으면 true를 반환하는 동등 연산자도 false를 반환

Symbol은 유일성을 보장한다.
Symbol을 만들때 괄호안에 문자열을 넣어 설명을 넣을 수도 있는데
이는 Symbol 생성에 영향을 끼치지 않으며 디버깅할때 용이하다.

const id = Symbol('id');
const id2 = Symbol('id');
id // Symbol(id);
id2 // Symbol(id);
id === id2 // false;
id == id2 // false;

사용 예제

다음과 같이 객체들의 key를 생성할때 Symbol를 사용한다.
이렇게 하면 keys(), values(), entries(), for in 구문에서
Symbol은 건너뛴다.
enumerable: false 이기 때문이다.
열거하려면 Object.getOwnPropertySymbols() 를 사용하면 된다.

배열에서 사용된 경우 열거된다.

JSON.stringify() 를 사용하면 Symbol 값은 문자열로 변환되지 않는다.

const id = Symbol('identify');
const method = Symbol('function');
const user = {
  name : "Mike",
  age : 30,
  [id] : 'myid', // Computed property
  [method](params){
  		return params;
  }
}
user // {name: 'Mike', age: 30, Symbol(identify): 'myid', Symbol(function): ƒ}
Object.keys(user); // ["name", "age"]
Object.values(user); // ["Mike", 30]
Object.entries(user); // [Array(2), Array(2)]
console.log(user[method](200)); // 200


const list = [Symbol("100"), Symbol("200"), 300];
for (let value of list) {
  	console.log(value);
}
/*
100
200
300
*/
const sym = Symbol("JSON");
const result = JSON.stringify({[sym]: "ABC", data: "hello"});
console.log(result); // '{"data":"hello"}'

Symbol.for()

전역 심볼.
{key: value} 형태로 생성되며
이때 key 값이 파라미터 값이 되고 Symbol() 로 생성한 값이 value 가 된다.
만약 true 와 같은 값이 파라미터로 들어가면 true를 문자열로 바꿔서 생성한다.

같은 key의 Symbol()이 없으면 만들고, 있으면 가져오기 때문에 하나의 심볼만 보장받을 수 있다.

Symbol 함수는 매번 다른 Symbol 값을 생성하지만,
Symbol.for 메소드는 하나를 생성한 뒤 키를 통해 같은 Symbol을 공유한다.
또 Symbol.for 메소드로 생성된 Symbol은 코드 어디에서든 사용 가능하다.

const id1 = Symbol.for('id');
const id2 = Symbol.for('id');
id1 === id2; // true, key 값으로 피교

Symbol.keyFor()

전역 심볼(Symbol.for로 만든 심볼)이 할당된 변수 이름을
매개변수로 넣어주면 key를 String 형으로 반환한다.
만약 없으면 undefined를 반환한다.

const id1 = Symbol.for('id');
Symbol.keyFor(id1); // "id"

Symbol.toString()

Symbol을 생성했던 형태를 문자열로 변환하여 반환한다.

console.log(Symbol("100").toString()); // Symbol(100)

const sym = Symbol.for("book");
console.log(sym.toString()); // Symbol(book)

console.log(Symbol().toString()); // Symbol()

Symbol.valueOf()

Symbol 객체의 원시 값을 반환합니다.

Symbol.toString() 이랑 출력 형태는 같지만 타입이 다르다.

Symbol.toString() 의 반환값은 String 이지만
Symbol.valueOf() 의 반환값은 Symbol 이다.

let sym = Symbol('foo');
console.log(sym.valueOf() === sym);  // true

description

Symbol 이름(또는 key)을 알고 싶을 때 사용하는 메소드 이다.
만약 파라미터 없이 만들어진 Symbol 이라면 undefined를 반환한다.

const id = Symbol('id 입니다');
console.log(id.description); // "id 입니다."

console.log(Symbol("test").description); // test
console.log(Symbol.iterator.description); // Symbol.iterator
console.log(Symbol().description); // undefined

숨겨진 Symbol Key 보는 법

  • 완전 Symbol를 못보는 것은 아니다.

Object.getOwnPropertySymbols()

객체의 프로퍼티 중 Symbol들만 배열에 담아 반환한다.

Object.getOwnPropertyNames() 는 Symbol을 반환하지 않는다.

const id = Symbol('id');
const user = {
  name : 'Mike',
  age : 30,
  [id] : 'myid'
};
Object.getOwnPropertySymbols(user); // [Symbol(id)]

Reflect.ownkeys()

객체의 Symbol형을 포함한 모든 key들을 배열로 반환

const id = Symbol('id');
const user = {
  name : 'Mike',
  age : 30,
  [id] : 'myid'
};
Reflect.ownkeys(user); // ["name", "age", Symbol(id)]

대부분의 라이브러리들은 위와 같은 메소드를 사용하지 않는다.
따라서 유일한 Property를 추가하고 싶을때 Symbol을 사용할 것.

협업/유지보수, 라이브러리 가공시 사용법

미리 작업한 코드에 내 코드를 삽입하면 어디선가 영향을 끼쳐 버그를 발생 시킬 우려가 있다.
이때 Symbol()을 사용하여 Property를 추가하면
예상치 못한 버그 발생 위험(이름 충돌)을 줄일 수 있다.

// 다른 개발자가 미리 만들어 놓은 객체
const user = {
  name : "Mike",
  age : 30,
};
// (많은 줄의 코드)
// 후 작업
// user.showName() = function() {}; 
// 이렇게 후 작업하면 사용자가 보는 메세지에 작업한 showName()이 보이게된다.
// 아래와 같이 작성하면 미리 작성된 코드에 영향을 끼치지 않는다.
const showNmae = Symbol("show name");
user[showName] = function(){
  console.log(this.name);
};
user[showName](); // 작업한 Symbol property 동작 시키기
//사용자가 접속하면 보는 메세지
for(let key in user){
  console.log(`His ${key} is ${user[key]}.`);
}
profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글