반응형
심볼(Symbol)
- primitive value => 유일무이하고 고유한 존재.
- 비공개 멤버에 대한 needs에서 탄생.
- 기본적인 열거대상에서 제외.
- 암묵적 형변환 불가.
`Symbol([string])` : 문자열이 아닌 타입은 자동으로 toString 처리한다.
const sb1 = Symbol()
const sb2 = Symbol()
console.log(sb1,sb2)
console.log(sb1 === sb2)
//결과: 오류
const sb1 = Symbol('symbol')
const sb2 = Symbol('symbol')
console.log(sb1, sb2)
console.log(sb1 === sb2)
//결과:
//Symbol(symbol) Symbol(symbol)
//false
const obj = {a:1}
const sb1 = Symbol(obj)
const sb2 = Symbol(obj)
console.log(sb1, sb2)
console.log(sb1 === sb2)
//결과:
//Symbol([object Object]) Symbol([object Object]) (자동으로 toString이 먹힌다.)
//false
const sb = Symbol(null)
console.log(typeof sb)
//결과:
//symbol
- 위의 Symbol의 코드들 결과를 보면 Symbol의 인자로 같은 문자열이 들어간다 해도 비교 연산으로 확인하면 false가 뜬다. 즉 아무리 같은 문자를 품고있어도 Symbol은 자신 하나로서 유일무이하다라고 볼 수 있다.
- 또 Symbol 인자에 들어간 문자열이 아닌 타입은 자동으로 toString 처리한다는 성질 또한 확인 할 수 있다.
- typeof로 타입은 확인 할 수는 있다.
객체 프로퍼티의 키로 활용
const NAME = Symbol('이름')
const GENDER = Symbol('성별')
const i = {
[NAME]: 'jinseok',
[GENDER]: 'male',
age: 25
}
const i2 = {
[NAME]: 'kim',
[GENDER]: 'male',
age: 26
}
const i3 = {
[NAME]: 'jin',
[GENDER]: 'male',
age: 30
}
console.log(i, i2, i3)
//결과:
//{age: 25, Symbol(이름): "jinseok", Symbol(성별): "male"} {age: 26, Symbol(이름): "kim", Symbol(성별): "male"} {age: 30, Symbol(이름): "jin", Symbol(성별): "male"}
- 위의 코드처럼 객체 프로퍼티 키로 활용할 수 있다.
- Symbol의 성질로 인해 쉽게 상수로서 쓸 수 있게 되었다. 하나의 고유의 식별자로 사용하는 것이다. i, i2, i3 객체 안에서만 쓸 수 있는 고유의 식별자라고 말할 수 있다.
심볼 탐색
Object.getOwnPropertySymbols(i).forEach(k => {
console.log(k, iu[k])
})
Reflect.ownKeys(i2).forEach(k => {
console.log(k, iu[k])
})
- 심볼을 탐색할 수 있는 것은 getOwnPropertySymbols과 ownKeys 메소드를 예로 들 수 있다. 다른 메소드 등등은 Symbol의 특성상 탐색할 수 없다.
private member 만들기
const obj = (() => {
const _privateMember1 = Symbol('private1')
const _privateMember2 = Symbol('private1')
return {
[_privateMember1]: '외부에서 보이긴 하는데 접근할 방법 X',
[_privateMember2]: 10,
publicMember1: 20,
publicMember2: 30
}
})() //즉시 실행 함수이다.
console.log(obj)
console.log(obj[Symbol('private1')])
console.log(obj[_privateMember1])
for (const prop in obj) {
console.log(prop, obj[prop]) // 오류
}
Object.keys(obj).forEach(k => { // 오류
console.log(k, obj[k])
})
Object.getOwnPropertyNames(obj).forEach(k => { // 오류
console.log(k, obj[k])
})
// 아래 방법들로는 접근 가능하나 마땅치 않음
Object.getOwnPropertySymbols(obj).forEach(k => {
console.log(k, obj[k])
})
Reflect.ownKeys(obj).forEach(k => {
console.log(k, obj[k])
})
- Symbol로 만든 위의 코드의 private member는 Java 언어에서의 캡슐화같은 외부에서 절대 건들 수 없게 만드는 코드를 자바스크립트에서 흉내냈다고 말할 수 있다.
- 실수로 혹은 기억이 안나서, 협업시 실수로 수정할 수 있는 여지를 방지하기 위하여 저렇게 캡슐화를 해준 것이다.
Symbol.for
public member이며 전역공간에서 공유되는 심볼이다. 그냥 Symbol과 전혀 반대라고 보면 된다.
const COMMON1 = Symbol.for('공유심볼')
const obj = {
[COMMON1]: '공유 프로퍼티 키값, 어디서든 접근 가능'
}
console.log(obj[COMMON1]) // 결과: 공유심볼
const COMMON2 = Symbol.for('공유심볼')
console.log(obj[COMMON2]) // 결과: 공유심볼
console.log(COMMON1 === COMMON2) // 결과: true
const UNCOMMON = Symbol('비공유심볼')
const commomSymbolkey1 = Symbol.keyFor(COMMON1)
const commomSymbolkey2 = Symbol.keyFor(COMMON2)
const commomSymbolkey2 = Symbol.keyFor(UNCOMMON)
const obj = (() => {
const COMMON1 = Symbol.for('공유심볼')
return {
[COMMON1]: '공유할 프로퍼티 키값. 어디서든 접근 가능'
}
})() //즉시 실행 함수
const COMMON2 = Symbol.for('공유심볼')
console.log(obj[COMMON2])
//결과:
//공유할 프로퍼티 키값. 어디서든 접근 가능
- Symbol.for은 그냥 Symbol과 다르게 전역공간에서 공유될 수가 있다.
- 위의 코드를 보면 Symbol.for이 공용으로 쓰여 어느 변수에 선언되든 그냥 Symbol과 다르게 똑같은 값 결과를 보여주는 것을 확인 할 수있다.
표준 Symbol
const arr = [4, 5, 6]
arr[Symbol.isConcatSpreadable] = true
console.log([1, 2, 3].concat(arr))
arr[Symbol.isConcatSpreadable] = false
console.log([1, 2, 3].concat(arr))
//결과:
//[1, 2, 3, 4, 5, 6]
//[1, 2, 3, Array(3)]
- Symbol.isConcatSpreadable: array의 `concat` 메소드에 인자로 넘길 때 이를 flatten(접을지)할지 여부를 가리키는 boolean값 (default: true)
- Symbol.hasInstance: instance instanceof constructor` 명령은 내부적으로 `constructor[Symbol.hasInstance](instance)` 으로 동작.
class Person {
constructor (name) { this.name = name}
}
const jin = new Person('jinseok')
console.log(jin.toString())
Person.prototype[Symbol.toStringTag] = 'PERSON'
console.log(jin.toString())
//결과
//[object Object]
//[object PERSON]
- Symbol.toStringTag: `Object.prototype.toString`이 호출되었을 때 어떤 명칭을 반환할 지를 지정 가능.
표준 심볼의 다양한 활용
const str = '이 _ 문자열을 _ 이렇게 _ 나누어라.'
String.prototype[Symbol.split] = function (string) {
let result = ''
let residue = string
let index = 0
do {
index = residue.indexOf(this)
if(index <= -1) {
break
}
result += residue.substr(0, index) + '/'
residue = residue.substr(index + this.length)
} while (true)
result += residue
return result
}
console.log(str.split(' _ '))
// 결과:
// 이/문자열을/이렇게/나누어라.
- Symbol.split: 문자열을 나누는 조건 설정
반응형
'프로그래밍 개발 > JS ES6+' 카테고리의 다른 글
Javascript ES6+ Map (0) | 2020.12.16 |
---|---|
Javascript ES6+ Set (0) | 2020.12.16 |
Javascript ES6+ Destructuring assignment (0) | 2020.12.14 |
Javascript ES6+ Function 함수 (0) | 2020.12.14 |
Javascript ES6+ Arrow Function (0) | 2020.12.11 |
댓글