회고록 블로그

[공부 필기] JavaScript 문법 공부 23일차 (1) 본문

2. 프로그래밍 언어 공부/JavaScript

[공부 필기] JavaScript 문법 공부 23일차 (1)

김간장 2022. 5. 24. 17:39

※ 필자는 초초초보자입니다.

※ 틀린 내용에 대한 피드백은 언제든지 환영합니다.

 

 

공부하고 있는 자료 : modern JavaScript tutorial 

https://ko.javascript.info/symbol

 

심볼형

 

ko.javascript.info

 

✅ 심볼형

- 자바스크립트 가능한 객체 프로퍼티 키 : 문자형 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

 

ECMAScript® 2023 Language Specification

The first and subsequent editions of ECMAScript have provided, for certain operators, implicit numeric conversions that could lose precision or truncate. These legacy implicit conversions are maintained for backward compatibility, but not provided for BigI

tc39.es

 

- 자바스크립트 내부에서 시스템 심볼을 사용하면 Symbol.* 로 접근할 수 있다.

 

 

※ 심볼을 완전히 숨기는 방법은 없다고 한다.

    Object.getOwnPropertySymbols(obj) 내장 메서드를 사용하면 모든 심볼을 볼 수 있으며

    Reflect.ownKeys(obj)는 심볼형 키를 포함한 객체의 모든 키를 반환한다고 한다.

 

Comments