[공부 필기] JavaScript 문법 공부 23일차 (1)
※ 필자는 초초초보자입니다.
※ 틀린 내용에 대한 피드백은 언제든지 환영합니다.
공부하고 있는 자료 : modern JavaScript tutorial
https://ko.javascript.info/symbol
✅ 심볼형
- 자바스크립트 가능한 객체 프로퍼티 키 : 문자형 or 심볼형
► 숫자형, 불린형 불가
- 프로퍼티 키가 심볼형일 때
► 유일한 식별자(unique identifier) 만들고 싶을 때 사용
► 심볼을 만들 때 설명을 붙일 수 있다. (= 심볼 이름)
"use strict";
// 심볼형
let id1 = Symbol();
let id2 = Symbol('id2'); // 심볼 이름이 id2인 심볼
// 문자형
let user1 = {};
let user2 = new User('soy', 1);
function User(name, age) {
this.name = name;
this.age = age;
}
- 심볼은 유일성이 보장되는 자료형이므로 심볼 이름이 동일해도 상관없다.
► 심볼 이름은 어떤 것에도 영향을 받지 않으며 이름표 역할만 한다
✅ 심볼 유의사항
- 문자형으로 자동 형 변환되지 않는다.
- 심볼형 값은 다른 자료형으로 암시적 형 변환(자동 형 변환) 되지 않는다.
► alert 등을 통해 문자열로 출력하려고 하면 에러가 발생한다.
"use strict";
// 심볼형
let id1 = Symbol('id2');
let id2 = Symbol('id2'); // 심볼 이름이 id2인 심볼
alert(id1); //Uncaught TypeError: Cannot convert a Symbol value to a string
- 만약 문자열로 형 변환이 필요하다면 .toString() 메서드를 사용한다.
// 심볼형
let id1 = Symbol('id2');
let id2 = Symbol('id2'); // 심볼 이름이 id2인 심볼
alert(id1.toString()); //Symbol(id2)
- 또한 for...in 에서는 배제된다.
► 프로퍼티 키가 심볼이면 for...in 반복문에서는 배제된다.
► Object.keys(user)에서도 키가 심볼인 프로퍼티는 배제된다. ('심볼형 프로퍼티 숨기기'라는 원칙 덕분)
► 하지만 Object.assign은 키가 심볼인 프로퍼티도 복사한다.
(일관성이 없어보이지만 의도된 설계라고 한다)
(객체를 복사하거나 병합할 때, 심볼을 모두 포함하여 프로퍼티를 전부 사용하고 싶을 것이라는 생각 때문에)
"use strict";
let id = Symbol("id");
let user = {
name: 'soy',
[id]: 411,
age: 1
};
for (let key in user) {
alert(key); // name과 age만 출력된다.
}
✅ 숨김(hidden) 프로퍼티
- 심볼을 통해 숨김(hidden) 프로퍼티를 만들 수 있다. ('심볼형 프로퍼티 숨기기'라는 원칙 덕분)
► 외부 코드에서 접근 불가능
► 값도 덮어쓸 수 없는 프로퍼티
- 어떠한 객체에 식별자를 붙여주는 상황이라고 가정
► 이때 식별자를 붙여주는 것은 심볼을 이용할 수 있다.
► 심볼 덕분에 식별자는 숨김 프로퍼티가 된다.
"use strict";
let user = {
name: 'soy',
};
let id = Symbol('id');
user[id] = 1;
console.log(user[id]); // 결과 : 1
- 심볼을 사용하는 것과 그냥 문자열 id를 사용하는 것에는 아래와 같은 차이가 있다.
► 만약 객체 User가 서드파티 코드에서 가져온 객체라면? => 함부로 새로운 프로퍼티를 추가할 수 없다. (= 문자열 id를 프로퍼티 키로 추가할 수 없다)
► 하지만 심볼은 서드파티 코드가 접근할 수 없기 때문에
심볼을 이용해서 식별자를 부여할 수 있는 것
► 또 다른 이유는 심볼은 유일성이 보장되기 때문에, 이름이 같더라도 충돌하지 않는다는 점이다.
► 문자열은 이름이 같으면 충돌할 가능성이 있다.
※ 용어 정리. 서드 파티(Third Party)
- 다른 회사 제품에 이용되는 소프트웨어나 하드웨어를 개발하는 회사를 의미한다.
- 하드웨어 생산자와 소프트웨어 개발자의 관계를 나타내는 용어이다.
하드웨어 생산자가 직접 소프트웨어를 개발하면 퍼스트 파티(First Party),
하드웨어 생산자와 직접적인 관계없이 소프트웨어 개발하는 회사를 서드 파티(Third Party)라고 부른다.
- 이를테면 아이폰을 처음 샀을 때 포함되어 있는 기본 순정 앱은 퍼스트 파티 앱이고
OS 제조사의 스토어 등(애플 스토어 등)에서 제공하는 소프트웨어 애플리케이션은 서드 파티 앱이 될 것이다.
✅ Symbols in a literal
- 객체 리터럴을 사용할 때는 대괄호를 사용해서 심볼형 키를 만들어야 한다.
"use strict";
let id = Symbol("id");
let user = {
name: 'soy',
[id]: 0411, //"id": 0411 을 하면 심볼이 아니라 문자열 id가 된다.
}
✅ 전역 심볼
- 보통 심볼의 설명이 같아도 모두 다른 심볼로 취급되지만
심볼의 설명이 같은 심볼은 모두 같은 개체를 가리키도록 하고 싶을 수도 있다.
- 이때, 사용하는 방법이 전역 심볼 레지스트리 안에 심볼을 만들고 접근하는 것이다.
- 전력 레지스트리 안에 있는 심볼을 읽거나, 새로운 심볼을 생성할 때 : Symbol.for(key) 사용
"use strict";
// 전역 레지스트리에서 심볼 읽기
let id = Symbol.for("id"); // id라는 심볼이 존재하지 않으면 새로운 심볼을 만든다.
// 전역 레지스트리에서 심볼 읽기
let isId = Symbol.for("id"); // id라는 심볼이 존재하므로 해당 심볼을 반환한다.
console.log(id === isId); //true
console.log(id); // Symbol(id)
- Symbol.for 메서드를 호출하면 이름이 id인 심볼을 반환한다.
없으면, 새로운 심볼을 만들고 레지스트리 안에 저장한다.
- 전역 심볼 레지스트리 안에 있는 심볼은 [전역 심볼]이라고 한다.
- 반대로 [심볼]을 이용해서 심볼의 설명(심볼 이름)을 얻고 싶다면 Symbol.keyFor(sym)을 이용하면 된다.
► 단, Symbol.keyfor은 전역 심볼에만 사용할 수 있다.
► 전역 심볼이 아닌 인자가 넘어오면 undefined 반환
"use strict";
let id = Symbol.for("id"); // 심볼을 찾음
console.log(id); // Symbol(id)
// ...
// ...
// ...
// 여러코드들
// ...
// ...
// ...
let isSym = Symbol.keyFor(id); // 심볼의 설명(심볼 이름)을 찾음
console.log(isSym); // id
- 전역 심볼이 아닌 심볼들은 description이 있다.
일반 심볼에서 심볼 이름을 얻고 싶다면 description 프로퍼티를 사용하면 된다.
- 예시
"use strict";
let id1 = Symbol("id001");
let id2 = Symbol.for("id002");
let symName;
if (symName = Symbol.keyFor(id1))
console.log(symName);
else
console.log(id1.description);
✅ 시스템 심볼
- 시스템 심볼 : 자바스크립트 내부에서 사용되는 심볼
- 객체를 미세 조정하는데 사용된다. (내장 메서드 등의 기본 동작을 입맛대로 변경할 수 있다)
- 자바스크립트 명세서에 따르면 잘 알려진 심볼(well-known symbols)은 아래와 같은 것들이 있다.
► Symbol.asyncIterator
► Symbol.hasInstance
► Symbol.isConcatSpreadable 등등
► 출처 및 참고 URL : https://tc39.es/ecma262/#sec-well-known-symbols
- 자바스크립트 내부에서 시스템 심볼을 사용하면 Symbol.* 로 접근할 수 있다.
※ 심볼을 완전히 숨기는 방법은 없다고 한다.
Object.getOwnPropertySymbols(obj) 내장 메서드를 사용하면 모든 심볼을 볼 수 있으며
Reflect.ownKeys(obj)는 심볼형 키를 포함한 객체의 모든 키를 반환한다고 한다.