기본형(Primitive Value)
주소 값에 값이 그대로 들어옴.
Number String Boolean null undefined Symbol
참조형(Reference Value)
기본 주소 값 외에 별개의 데이터가 존재
Object Array function Map Set WeakMap WeakSet
Symbol([string]): 문자열이 아닌 타입은 자동으로 toString 적용
new 연산자를 사용하지 않음
const sb1 = Symbol()
const sb2 = Symbol()
console.log(sb1, sb2) // Symbol() Symbol()
console.log(sb1 == sb2) // false
console.log(sb1 === sb2) // false
const sb1 = Symbol('symbol')
const sb2 = Symbol('symbol')
console.log(sb1, sb2) // Symbol(symbol) Symbol(symbol)
console.log(sb1 === sb2) // false
Symbol로 선언된 프로퍼티는 열거 대상이 아닙니다.
외부에서 Symbol로 선언된 프로퍼티에는 접근이 불가능. >> 은닉화
객체 내부에서 식별자로만 사용된다.
const NAME = Symbol('이름')
const GENDER = Symbol('성별')
const kang = {
[NAME]: 'kang',
[GENDER]: 'male',
age: 27,
}
const kim = {
[NAME]: 'kim',
[GENDER]: 'female',
age: 24
}
console.log(kang, kim)
// { age: 27, [Symbol(이름)]: 'kang', [Symbol(성별)]: 'male' }
// { age: 24, [Symbol(이름)]: 'kim', [Symbol(성별)]: 'female' }
Reflect.ownKeys(kang).forEach(i => {
console.log(i, kang[i])
// age 27
// Symbol(이름) kang
// Symbol(성별) male
})
캡슐화를 위해 ... private 흉내만 내는 정도
const obj = ( () => {
// 내부 함수에서 Symbol 선언한 값은 블록 스코프안에서만 유효
const _privateMember1 = Symbol('private1')
const _privateMember2 = Symbol('private2')
return {
[_privateMember1]: '외부에서 보이긴 하는데 접근할 방법이 애매해...',
[_privateMember2]: 10,
publicMember1: 20,
publicMember2: 30
}
})() // 즉시 실행 함수
console.log(obj)
console.log(obj[Symbol('private1')]) // undefined
console.log(obj[_privateMember1]) // ReferenceError: _privateMember1 is not defined
obj[Symbol('private1')]
: 새로운 Symbol을 만든 것이므로 접근이 불가능
Symbol('private1') === Symbol('private1') // false
obj[_privateMember1]
: 외부에서 접근 가능한 _privateMember1 변수가 없으므로 오류
for( const prop in obj){
console.log(prop, obj[prop])
// publicMember1 20
// publicMember2 30
}
Object.keys(obj).forEach(item => {
console.log(item, obj[item])
// publicMember1 20
// publicMember2 30
})
Symbol에 접근은 가능하나 정상적인 접근법이 아니다.
Object.getOwnPropertySymbols(obj).forEach(i =>{
console.log(i, obj[i]) // Symbol(private1) 외부에서 보이긴 하는데 접근할 방법이 애매해...
// Symbol(private2) 10
})
Reflect.ownKeys(obj).forEach(i => {
console.log(i, obj[i]) //publicMember1 20
// publicMember2 30
// Symbol(private1) 외부에서 보이긴 하는데 접근할 방법이 애매해...
// Symbol(private2) 10
})
public memeber: 전역 공간에서 공유되는 심볼.
const a = Symbol.for('public')
const b = Symbol.for('public')
a === b // true
Symbol로 선언했을 때에는 항상 새로운 값이 생성되므로 a===b
는 false였습니다.
하지만 Symbol.for()로 선언하는 경우는 다릅니다.
Symbol.for('public')
: public이라는 문자열이 처음 생성된 경우 메모리 공간에 그 값을 저장합니다. 이후 또 다시 public이라는 문자열로 생성 시 이미 저장해둔 값을 가져와 사용합니다. 즉, public 문자열을(메모리) 참조합니다.
그렇기 때문에 a===b
는 true 입니다.
const obj = (() => {
const COMMON1 = Symbol.for('public')
return {
[COMMON1]: '공유할 프로퍼티 값. 어디서든 접근 가능.'
}
})();
obj[Symbol.for('public')] // "공유할 프로퍼티 값. 어디서든 접근 가능."
public 문자열로 Symbol.for를 생성했으므로 public이라는 문자열만 알고 있으면 어디서든 접근이 가능합니다.
const COMMON1 = Symbol.for('public')
const COMMON2 = Symbol.for('public')
const UNCOMMON = Symbol('비공유')
const commonSymbolKey1 = Symbol.keyFor(COMMON1) // public
const commonSymbolKey2 = Symbol.keyFor(COMMON2) // public
const commonSymbolKey3 = Symbol.keyFor(UNCOMMON) // undefined
Symbol.for()를 사용하여 만든 변수에 대해서는 Symbol.keyFor()을 사용할 수 있다.
선언할 때 사용한 문자열을 출력해줌.