객체 property key 는 오직 문자형
과 아래에서 배울 심볼형(symbol)
만을 허용한다.
const obj = {
1: '1이다',
false: '거짓',
}
const name = Object.keys(obj);
console.log(name); // ["1","false"]
console.log(obj['1']); // "1이다."
console.log(obj['false']); // "거짓"
자바스크립트의 심볼(Symbol)은 ES6에서 새롭게 추가되었으며, "심볼
" 데이터 형식은 값으로 익명의 객체 속성(object property)을 만들 수 있는 특성을 가진 원시 데이터 형식(primitive data type)
이다.
심볼은 아래와 같이 만든다.
심볼은 유일한 식별자를 만들 때 사용한다.
symbol
은 new
를 붙이지 않는다.
const a = Symbol();
const b = Symbol();
console.log(a); // Symbol()
console.log(b); // Symbol()
console.log(a === b); // false
console.log(a == b); // false
심볼형은 유일성 이 보장된다. 전체의 코드 중에 하나라는 뜻이다.
심볼을 만들 때 설명을 붙여 줄 수 있고 이는 디버깅*을 할 때 편리하다.
디버깅*이란 무엇인가요?
디버깅은 모든 소프트웨어에서 소스 코드의 오류 또는 버그를 찾아서 수정하는 과정이다. 소프트웨어가 예상대로 작동하지 않으면 컴퓨터 프로그래머는 오류가 일어나는 원인을 알아내기 위해 코드를 분석한다.
const id = symbol('id');
설명에는 문자열을 전달해 주면 되는데, 이 문자는 심볼 생성에는 어떠한 영향도 주지 않는다.
설명이 똑같은 걸 또 만들어도 둘다 다르다(false)고 나온다.
const id1 = Symbol('id');
const id2 = Symbol('id');
console.log(id1); //Symbol(id)
console.log(id2); //Symbol(id)
console.log(id1 === id2); //fasle
console.log(id1 == id2); //fasle
const id = Symbol('id');
const user = {
name : 'mike',
age : 30,
[id] : 'myid',
}
console.log(user); // {name: 'mike', age: 30, Symbol(id): 'myid'}
console.log(user[id]); // "myid"
아래의 메서드들은 key 가 symbol형
인 애들은 건너뛴다.
마찬가지로 for...in 을 써도 건너 뛴다.
Object.keys(user); // ["name","age"]
Object.values(user); // ['mike', 30]
Object.entries(user); // [Array(2), Array(2)]
for(let a in user){
console.log(a);
// "name"
// "age"
}
❓ 심볼(symbol) 은 어디에서 쓸까?
'심볼(symbol)'은 유일한 식별자(unique identifier)를 만들고 싶을 때 사용합니다.
특정 객체의 원본 객체는 건드리지 않고 속성을 추가할 수 있다.
다른 사람이 만들어 놓은 객체에 객체 자신만의 속성을 추가해서 덮어 씌우면 안 되기 때문이다.
원본 데이터가 다른 데서 쓰이고 있는데, 내가 추가한 프로퍼티가 예측 불가능하게 튀어 나오면 안 되기 때문이다.
symbol.for
메서드는 하나를 생성한 뒤 키를 통해 같은 심볼을 공유한다.const id1 = Symbol.for('id');
const id2 = Symbol.for('id');
console.log(id1 === id2); // true
아까와 다르게 id1 과 id2 가 동일하다고 나타난다.
이것을 전역 심볼
이라고 부르며, 코드 어디에서든 사용할 수 있다.
이름을 얻고 싶다면 Symbol.keyFor()
를 사용하면 된다.
Symbol.keyFor(id1); // "id"
전역 심볼이 아닌 심볼은 keyFor
을 사용할 수 없다.
대신 discription
으로 알 수 있다.
const id = Symbol('id다');
console.log(id.description); // 'id다'
심볼을 완벽히 숨길 수 있는 방법은 없다.
const id = Symbol('id');
const user = {
name : 'mike',
age : 30,
[id] : 'meid'
}
// 심볼들만 볼 수 있다.
Object.getOwnPropertySymbols(user); // [Symbol(id)]
// 심볼형 키를 포함한 객체의 모든 키를 보여 준다.
Reflect.ownKeys(user); // ['name', 'age', Symbol(id)]
다만, 대부분의 라이브러리들은 해당 메서드를 많이 사용하지 않기 때문에 걱정하지 말고 유일한 프로퍼티를 사용하고 싶을 때 심볼을 사용하자.
아래 다른 개발자가 작성한 코드에 메서드를 추가 하여 보자.
// 다른 개발자가 만들어 놓은 객체
const user = {
name : 'mike',
age : 30,
};
// 내가 새롭게 하는 작업
user.showName = function(){}
// 사용자가 접속하면 보는 메시지
for (let x in user) {
console.log(`His ${x} is ${user[x]}.`);
}
/*
"His name is mike."
"His age is 30."
"His showName is function () {}."
*/
❌ 심볼을 사용하지 않았을 경우 내가 새롭게 작업한 코드로 인해 나오지 말아야 할 문구 ("His showName is function () {}.") 가 나오는 문제가 발생한다.
위 문제를 심볼을 사용하여 고쳐 보자.
// 다른 개발자가 만들어 놓은 객체
const user = {
name : 'mike',
age : 30,
};
// 내가 새롭게 하는 작업
const showName = Symbol('showName');
user[showName] = function (){
console.log(this.name);
}
user[showName] ();
// 사용자가 접속하면 보는 메시지
for (let x in user) {
console.log(`His ${x} is ${user[x]}.`);
}
/*
"mike"
"His name is mike."
"His age is 30."
*/
이렇게 하면 내가 새롭게 작업한 메서드도 잘 작동하며, 다른 개발자가 작성한 코드에도 영향을 미치지 않고 메서드를 추가할 수있다.
동일한 메서드가 있는지를 걱정할 필요도 없고, 다른 개발자가 만들어 놓은 프로퍼티에 덮어씌울 일이 없다는 것이 심볼의 장점이다.