TIL/JS

Symbol

yyeon111 2023. 3. 27. 23:44

Symbol을 검색 해 보면 절대 중복되지 않는 유일무이한 값이라고 설명 되어 있다.

그런데 공부를 해 보니, 이 말로 Symbol을 설명하기엔 부족 하다고 느꼈다.

 

Symbol은 주로 키로 사용한다.

이유는 외부로 부터 접근을 차단 할 수 있기 때문이다.

Symbol 데이터 타입을 그대로 key로 넣는다면, Object.prototype.includes처럼, 같은 데이터로 인식하지 않는다.

객체는 무조건, 주소가 들어가 있기 때문에 보기에는 같아보여도 결국 다른 값이라는 것이 여기서도 나온다.

const obj = {
  user: 'abcd',
  [Symbol('passowrd')]: 123,
}

console.log(obj); // { user: 'abcd', [Symbol(passowrd)]: 123 }
console.log(obj[Symbol('password')]); // undefined -> 다른 곳을 가리킴 보기에만 같다.

하지만, 변수에 담게 된다면 같은 데이터 주소를 가리키고 있기 때문에 접근이 가능하다.

그렇다 하더라도, 클라이언트는 객체명을 알고 조회하면 변수의 값이 보이기 때문에, 실제 Symbol의 키를 알 수 없어 접근이 가능하지 않다.

const password = Symbol('secret');

const obj = {
  email: 'abcd@aaa.com',
  [password]: 123,
}

console.log(obj); // { email: 'abcd@aaa.com', [Symbol(secret)]: 123 }
console.log(obj[Symbol['secret']]); //undefined

이렇게, Symbol자체에 접근 할 수 없는 특징이 유일무이한 값이라고 하는 것 같다.

 

이러한 말 때문에, 그렇다면 Symbol은 한 번밖에 사용 하지 못하는 것인가 생각을 하게 된다.

하지만 실습을 해 보면, 같은 Symbol은 얼마든지 생성 할 수 있다.

말하자면, 같은 심볼이지만 같지 않은 심볼이다.

보이는 값은 같지만, 다른 것으로 인식 한다는 것이다.

이 또한 객체와 같은 특징으로 볼 수 있다.

const user1 = Symbol('password');
const user2 = Symbol('password');
console.log(user1 === user2); // false

 

또한, Symbol은 for..in으로 접근이 불가능 해서, Symbol을 제외한 프로퍼티만 순회된다.

Object의 메서드 keys, values, entries로 접근 시에는 object 자체에 대한 접근이 불가능하다.

또한, Object.getOwnPropertyNames로도 접근시에는 Symbol을 제외한 프로퍼티만 배열로 반환한다.

하지만, Object.getOwnPropertyDescriptors, Object.getOwnPropertySymbols는 순회가 가능하다.

 

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

 

만든 심볼은 보기에는 같은 값 같지만, 실제로는 다른 것으로 인식 한다고 했다.

그런데 변수처럼 같은 심볼임을 나타 낼 수 있는 방법도 있다.

 

⚪ Symbol.for()

심볼의 정적 메서드 for을 사용해서, 전역 심볼 레지스트리에 등록 할 수 있다.

등록 된 변수는 사용 할 때 마다 저장 해둔 심볼을 꺼내서 마치 변수 처럼 사용 할 수 있다.

const password = Symbol.for('password');
const user = Symbol.for('password');

console.log(password === user); // true

const obj = {
  [user]: 'name'
};

console.log(
  obj[Symbol.for('password')] // name
);

⚪ Symbol.keyFor()

전역 심볼 레지스트리에 등록된 심볼의 값을 볼 수 있다.

const password = Symbol.for('password');
const user = Symbol.for('password');

console.log(password === user); // true

const obj = {
  [user]: 'name'
};

console.log(
  obj[Symbol.for('password')]
);

console.log(Symbol.keyFor(user)); //password
console.log(Symbol.keyFor(Symbol.for())); // undefind
console.log(Symbol.keyFor(anonymous)); // error

💡 keyFor는 식별자로 인자로 전달하고, 변수의 값이 전역 레지스트리에 등록 되어 있을 때만 조회가 가능하다.

변수 없이 사용하면 문법 상으로 맞지도 않고, 에러는 안나지만 undefined가 된다.

등록되지 않은 변수를 인자로 전달 했을 경우, 에러가 난다.

 

🤔 의문점

심볼을 공부 해 보니, 심볼을 키로 지정 했을 때 심볼을 가리킬 수 없어 변수를 사용하는데, 그렇다면 이러한 측면에서 굳이 전역 심볼 레지스트리의 쓰임이유를 모르겠다.

사용 해 보니 변수와 같이 같은 심볼에 값을 변경 할 경우 변수처럼 똑같이 덮어씌우기 때문이다.

심볼이 쓰인 경우를 많이 보지 못해서 아직 어떻게 써야할지 감이 잘 잡히지 않는 것 같다.

나중에 전역레지스트리를 사용한 코드를 많이 찾아봐야겠다.

'TIL > JS' 카테고리의 다른 글

2, 8, 16진법과 비트 연산  (0) 2023.03.28
JSON  (0) 2023.03.28
Object methods  (0) 2023.03.24
디스트럭쳐링 접근  (0) 2023.03.24
배열의 고차함수 메서드  (0) 2023.03.24