자바스크립트는 객체의 프로퍼티 키로 문자형과 심볼형만을 허용합니다.
Symbol ?
심볼은 유일한 식별자를 만들고 싶을 때 사용합니다.
let test = Symbol('테스트 심볼')
console.log(test) // Symbol(테스트 심볼)
심볼은 Symbol() 로 만들 수 있고,
괄호안에 '심볼 이름' 이라고 불리는 심볼의 대한 설명을 붙일 수 있습니다.
심볼은 유일성이 보장되는 자료형입니다.
때문에 심볼 설명이 동일한 여러 개의 심볼을 만들어도 각 심볼값은 다릅니다.
let test1 = Symbol('테스트 심볼')
let test2 = Symbol('테스트 심볼')
console.log(test1 == test2) // false
console.log(test1 === test2) // false
심볼값은 서로 다릅니다!!
심볼은 자동 형 변환이 안된다.
자바스크립트에서는 문자형으로의 암시적 형 변환이 비교적 자유롭게 일어납니다.
그렇기에 alert 함수가 거의 모든 값을 인자로 받을 수 있죠!
하지만 심볼값은 다른 자료형으로의 자동 형 변환이 되지 않습니다.
아래 코드는 에러가 발생합니다.
let test1 = Symbol('테스트 심볼')
alert(test1) // TypeError: Cannot convert a Symbol value to a string
문자열과 심볼은 근본이 다릅니다!
고로 우연히라도 서로의 타입으로 변환이 일어나서는 안됩니다.
자바스크립트에서는 언어 차원의 보호장치가 심볼형의 자동 형 변환을 막아줍니다.
심볼을 반드시 출력해야 한다면?
let test1 = Symbol('테스트 심볼')
alert(test1.toString()) // Symbol(테스트 심볼)
.toString() 메소드를 활용합니다.
심볼의 설명만 보고싶다면?
let test1 = Symbol('테스트 심볼')
console.log(test1.description) // 테스트 심볼
symbol.description 프로퍼티를 활용합니다.
symbol 로 숨김 프로퍼티 만들기
숨김 프로퍼티는 외부 코드에서 접근이 불가능하고 값의 쓰기가 불가능합니다!
심볼로 한번 만들어 봅시다!
1. 서드파티 코드에서 가져온 user 객체가 여러 개 있고,
이 객체를 활용해 어떤 작업을 해야 한다고 가정합시다.
let user = {
name: 'Lee'
}
2. user 객체는 다른 파일의 코드에서 가져왔기 때문에 함부로 프로퍼티를 추가할 수 없습니다.
이때 스크립트에서 심볼을 사용해서 만든 id라는 식별자는 user 객체를 가져온 코드에서 접근할 수 없기 때문에
가져온 코드에 변형없이 user 객체로 작업이 가능합니다.
let user = {
name: 'Lee'
}
let id = Symbol('유저 id')
user[id] = 1 // symbole 이름은 문자열이기 때문에 대괄호 표기법을 사용합니다.
console.log(user) // {name: 'Lee', Symbol(유저 id): 1}
console.log(user[id]) // 1
유저id라는 symbol 값이 1 인 user 객체 입니다.
3. 여기서 갑자기 또 다른 제 3의 스크립트에서 user객체를 사용해야 한다면?
그저 symbol 을 만들어 주면 됩니다.
let user = {
name: 'Kim'
}
let id = Symbol('유저 id')
user[id] = 12
console.log(user) // {name: 'Lee', Symbol(유저 id): 12}
console.log(user[id]) // 12
심볼의 유일성 덕분에 2번에서 만든 symbol 과 3번에서 만든 symbol 은 서로 다릅니다.
고로 각 파일에서 만든 식별자는 서로 충돌하지 않습니다.
만약 심볼 대신 문자열을 사용해 프로퍼티 키를 만들었다면
당연하게도 각 파일의 user.id 는 서로 충돌하여 덮어쓰기 되면서 난리가 날겁니다!!!!
symbol은 for...in문 에서 제외됩니다!
키가 심볼인 프로퍼티는 for..in 반목문의 대상에서 제외됩니다!
let pw = Symbol('pw')
let user = {
name: 'Kim',
id : 'go heaven',
[pw] : 1234
}
for(let key in user) {
console.log(`${key} : ${user[key]}`) // name : Kim
} // id : go heaven
심볼로 만든 pw는 출력되지 않았습니다.
symbol은 Object.keys() 에도 제외됩니다!!
console.log(Object.keys(user)) // ['name', 'id']
이러한 원칙 덕분에 외부 스크립트, 라이브러리에서는 심볼형 키를 가진 프로퍼티에는 접근이 불가능 합니다!
symbol은 Object.assign() 에서는 복사됩니다!!
Object.assign을 사용해 객체를 복사할 땐 심볼을 포함한 모든 프로퍼티가 복사됩니다!
let pw = Symbol('pw')
let user = {
name: 'Kim',
id : 'go heaven',
[pw] : 1234
}
let clone = Object.assign({},user)
console.log(clone) // {name: 'Kim', id: 'go heaven', Symbol(pw): 1234}
전역 Symbol
위의 예시와는 다르게
이름이 같은 심볼이 같은 개체를 가리키길 원하는 경우에 전역 symbol을 활용할 수 있습니다!
전역 심볼 레지스트리는 이런 경우를 위해 만들어졌습니다.
전역 심볼 레지스트리 안에 전역 심볼을 생성하면 해당 심볼 이름으로 여러 곳에서 접근할 수 있습니다.
전역 심볼은 Symbol.for(' 심볼이름 ') 을 통해 생성하고 읽을 수 있습니다.
심볼이름이 없으면 생성하고 있으면 읽어 옵니다!
let pw = Symbol.for('pw') // 전역 심볼이 생성됩니다.
let pwpw = Symbol.for('pw') // 위에서 생성된 전역 심볼을 리턴합니다!
console.log(pw == pwpw) // true
console.log(pw === pwpw) // true
Symbol.keyFor( )
Symbol.keyFor( 심볼 ) 을 활용하면 심볼 이름을 얻을 수 있습니다.
Symbol.for( ) 의 반대 개념이라고 이해합시다!
위 두 메서드는 전역 심볼에만 사용 가능합니다.
let pw = Symbol.for('pw 인데용?')
let pwpw = Symbol.for('pw 입니다.')
console.log(Symbol.keyFor(pw)) //pw 인데용?
console.log(Symbol.keyFor(pwpw)) //pw 입니다.
'Frontend > JS.info 정리' 카테고리의 다른 글
자료구조와 자료형 - 원시값의 메소드 (0) | 2022.01.16 |
---|---|
객체: 기본 - 객체를 원시형으로 변환하기 (0) | 2022.01.11 |
객체: 기본 - optional chaining ( ?. ) (0) | 2021.12.22 |
객체: 기본 - new , constructor (0) | 2021.12.21 |
객체: 기본 - method 와 this (0) | 2021.12.19 |