10.2 위크맵
WeakMap
은 다음 차이점을 제외하면 Map과 완전히 같습니다.
- 키는 반드시 객체여야 합니다.
- WeakMap의 키는 가비지 컬렉션에 포함될 수 있습니다.
- WeakMap은 이터러블이 아니며 clear() 메서드도 없습니다.
일반적으로 자바스크립트 코드는 어딘가에서 객체를 참조하는 한, 그 객체를 메모리에 계속 유지합니다.
예를 들어 Map의 키인 객체 o가 있다면, 자바스크립트는 Map이 존재하는 한 o를 메모리에 계속 유지합니다.
WeakMap에서는 그렇지 않습니다.
따라서 WeakMap은 이터러블이 될 수 없습니다.
가비지 콜렉션 중인 객체를 노출할 위험이 너무 크기 때문입니다.
WeakMap의 이런 특징은 객체 인스턴스의 전용(private) 키를 저장하기에 알맞습니다.
const SecretHolder = (function() {
const secrets = new WeakMap();
return class {
setSecret(secret) {
secrets.set(this, secret);
}
getSecret() {
return secrets.get(this);
}
}
})();
앞의 예제에서는 WeakMap과 그 위크맵을 사용하는 클래스를 함께 IIFE에 넣었습니다.
IIFE 외부에서는 그 인스턴스에 비밀스런 내용을 저장할 수 있는 SecretHolder 클래스를 얻게 됩니다.
비밀을 저장할 때는 setSecret 메서드를 써야만 하고, 보려 할 때는 getSecret 메서드를 써야만 합니다.
const a = new SecretHolder();
const b = new SecretHolder();
a.setSecret('secret A');
b.setSecret('secret B');
a.getSecret(); // "secret A"
b.getSecret(); // "secret B"
일반적인 Map을 써도 되지만, 그렇게 하면 SecretHolder 인스턴스에 저장한 내용은 가비지 콜렉션에 포함되지 않습니다.
음.. 저런 WeakMap 성질을 활용해서 아래처럼 쓰는건가..?
그럼 일반 브라우저 개발창 콘솔에서 접근 못하긴 하는데..
그냥 위의 식처럼쓰믄 브라우저 개발창 콘솔에서 접근이 가능함..
(function () {
const SecretHolder = (function() {
const secrets = new WeakMap();
return class {
setSecret(secret) {
secrets.set(this, secret);
}
getSecret() {
return secrets.get(this);
}
}
})();
const a = new SecretHolder();
const b = new SecretHolder();
a.setSecret('secret A');
b.setSecret('secret B');
a.getSecret(); // "secret A"
b.getSecret(); // "secret B"
})()