NaN
과 undefined
도 Set에 저장할 수 있다.true
를 반환하고, 아니라면 false
를 반환한다.boolean
으로 반환한다.https://velog.io/@dev_shu/%EC%99%9C-set.has%EB%8A%94-O1%EC%9D%B8%EA%B0%80
let setObj = new Set([1, 2, 3, 4, 5]);
setObj.add(6); // Set { 1, 2, 3, 4, 5, 6 }
setObj.delete(1); // Set { 2, 3, 4, 5, 6 }
setObj.has(0); // false
next()
메서드를 통해 반복시킬 수 있다.for..of
로 내부의 값을 순회할 수 있다.next()
메소드를 통해 직접 객체를 순회하여 결과값을 받을 수 있다.forEach
함수를 통해서도 내부를 순회할 수 있다.let setObj = new Set([1, 2, 3, 4, 5]);
const setIter = setObj.values();
console.log(setIter.next().value); // 1
for (const num of setObj) {
console.log(num); // 1, 2, 3, 4, 5
}
setObj.forEach((num) => console.log(num * 2)); // 2, 4, 6, 8, 10
key
와 value
로 이루어진 한 쌍의 데이터를 보관할 수 있다.key
와 value
값이 나온다.Object 와 다른 점이란?
Object
는 키에 무조건 문자열 혹은 심볼만 들어갈 수 있으나, Map
은 어떠한 자료형이던 전부 허용함. 심지어는 객체도 key 값으로 적용할 수 있다.Map
은 순회가 가능한 iterable 객체이나, Object
의 경우 그렇지 않다.Map
이 더 뛰어난 성능을 보여준다.key
와 value
로 이루어진 한 쌍의 엔트리를 추가한다.key
값과 대응하는 value
값이 이미 있다면, 이를 새롭게 업데이트 한다.key
값에 대응되는 value
값이 Map 객체 안에 있는지를 확인한다.value
값이 존재하지 않을 경우에는 결과로 undefined
를 리턴한다.key
값이 Map 객체 내부에 있는지를 확인하고 값을 제거한다.boolean
으로 반환한다.let mapObj = new Map();
mapObj.set('name', 'baik gwangin');
mapObj.set('job', 'student');
mapObj.set('age', 30);
map.set('age', 25); // age 값을 25로 업데이트.
mapObj.has('major'); // false
mapObj.get('age'); // 25
key
값을 삽입된 순서대로 순회할 수 있는 Iterator 객체를 반환한다.next()
메서드를 통해 반복시킬 수 있다.value
값을 삽입된 순서대로 순회할 수 있는 Iterator 객체를 반환한다.next()
메서드를 통해 반복시킬 수 있다.key
, value
값을 한 쌍으로 하는 iterator 객체를 반환한다.next()
메서드를 통해 반복시킬 수 있다.for..of
로 내부의 값을 순회할 수 있다.forEach
함수를 통해서도 내부를 순회할 수 있다.let MapObj = new Map([
['foo', 3],
['bar', {}],
['baz', undefined],
]);
const MapIter = MapObj.values();
console.log(MapIter.next()); // {value: 3, done: false}
for (const [key, value] of MapObj) {
console.log(`${key} ${value}`); // foo 3, bar [object Object], baz undefined
}
for (const key of MapObj.keys()) {
console.log(key); // foo, bar, baz
}
for (const value of MapObj.values()) {
console.log(value); // 3, {}, undefined
}
https://ui.toast.com/posts/ko_20210901 참조하여 더 정리해보자.
for..of
루프 사용이 불가하다.boolean
값을 리턴한다.const weakSet = new WeakSet();
const obj1 = {};
const obj2 = function () {};
weakSet.add(window);
weakSet.add(obj1);
weakSet.add(obj2);
weakSet.has(obj1); // true
weakSet.delete(obj1);
weakSet.has(obj1); // false
key
로 넣을 수 있다.TypeError
에러가 발생한다.key
로 쓰인 객체는 Garbage Collector 의 수거 대상이 된다.const weakMap = new WeakMap();
const key1 = {};
const key2 = function () {};
const key3 = window;
weakMap.set(key1, 11);
weakMap.set(key2, 'test');
weakMap.set(key3, undefined);
weakMap.set('key4', 'key'); // Uncaught TypeError: Invalid value used as weak map key
key
와 value
로 이루어진 한 쌍의 엔트리를 추가한다.key
가 객체가 아닐 경우, TypeError
를 발생시킨다.key
값에 대응되는 value
값이 WeakMap 객체 안에 있는지를 확인한다.value
값이 존재하지 않을 경우에는 결과로 undefined
를 리턴한다.key
값이 WeakMap 객체 내부에 있는지를 확인하고 값을 제거한다.true
를, 키를 찾을 수 없거나 키가 객체가 아닌 경우는 false
를 반환한다.boolean
으로 반환한다.keys()
, values()
) 를 지원하지 않는다.// 하단의 객체는 obj 라는 식별자가 참조하여 접근이 가능하다.
let obj = { a: 10, b: 20 };
// 하지만 참조 값을 null 로 덮어씌울 경우 더 이상 객체에 접근이 불가하다.
// 따라서 해당 객체 ({a: 10, b: 20}) 는 자동으로 메모리에서 삭제된다.
obj = null;
let obj = { a: 10, b: 20 };
let arr = [obj];
// obj 식별자의 참조 값을 기존의 객체에서 null로 덮어 씌웠다.
obj = null;
// 하지만 객체를 참조하는 배열이 메모리 상에 남았기에 GC의 대상이 되지 않음.
// array[0] 을 통해 해당 객체의 값을 얻는 것 또한 가능하다.
console.log(arr[0]); // { a: 10, b: 20 }
key
값에 객체를 키로 추가한다면 더 이상 GC를 막지 않게 된다.let obj = { a: 10, b: 20 };
let wm = new WeakMap();
let ws = new WeakSet();
// obj가 참조한 객체를 key로 가지는 한 쌍의 엔트리를 생성.
wm.set(obj, 'foo');
console.log(wm.get(obj)); // foo
ws.add(obj);
// obj 식별자의 참조 값을 null로 덮어씌워 더 이상 객체에 접근하지 못하게 함.
// 이로 인해 WeakMap 안에 저장되었던 기존의 객체 또한 자동으로 소멸됨.
obj = null;
console.log(wm.get(obj)); // undefined
keys()
, values()
같은 메서드가 없다function createLargeClosure() {
const largeObj = {
a: 1,
b: 2,
str: new Array(1000000).join('x'),
};
const lc = function largeClosure() {
return largeObj;
};
return lc;
}
const memo = new WeakMap();
function memoize(obj) {
if (memo.has(obj)) {
return memo.get(obj);
}
const result = obj.a + obj.b;
memo.set(obj, result);
return result;
}
function start() {
const lcObj = createLargeClosure();
const timer = setInterval(() => {
memoize(lcObj);
}, 1000);
setTimeout(function () {
clearInterval(timer), 5001;
});
}