자바스크립트 E6(ES2015)가 나오면서, 편리한 자료구조인 ES2015-Collections( Map, Set )가 등장했습니다.
자바스크립트의 Map 과 Set의 API가 타 언어에 비해 조금 다르더라도,
타 언어와 많이 다르지 않기 때문에 사용하는것이 어렵진 않습니다.
다만, 순회하는 방법이 조금 독특하기 때문에 이번 포스팅을 하게 되었습니다.
forEach 메서드로 순회하기
Map, Set에서의 forEach( [Map or Set].prototype.forEach )는 Array의 forEach( Array.prototype.forEach )와 비슷하지만 조금 다릅니다.
Array의 forEach가 받는 콜백함수의 인수는 순서대로 값, 인덱스, 배열 순으로 들어옵니다.
하지만 Map, Set에서의 forEach가 받는 콜백함수의 인수는 순서대로 값, 키, 오브젝트(Map or Set) 로 들어옵니다.
Set의 콜백함수는 key 대신에 value2가 들어옵니다. value2는 value와 똑같습니다.
아래의 예시와 "개별 값으로 순회 하기" 설명을 확인해주세요.
[ Ex) JavaScript / TypeScript ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // JavaScript const map = new Map(); const set = new Set(); // TypeScript const map = new Map<string, string>(); const set = new Set<string>(); map.set('name', 'Mommoo'); map.set('age' , 'secret'); set.add('Mommoo'); set.add('secret'); map.forEach((value, key, mapObject) => console.log(key +' , ' +value)); // name , Mommoo // age , secret set.forEach((value1, value2, setObject) => console.log(value1 +' , '+ value2)); // Mommoo , Mommoo // secret , secret | cs |
for.. of 문법으로 순회하기
forEach 방법은 순회 중간에 continue, break, return 과 같은 루프 기능을 못쓰지만,
ES6(ES2015)에서 새로나온 for.. of 문법을 사용하면, 가능합니다.
Map의 for.. of로 호출되는 값은 키와 벨류가 들어가 있는 배열 입니다.
Set의 for.. of로 호출되는 값은 벨류입니다.
[ Ex) JavaScript ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | const map = new Map(); const set = new Set(); map.set('name', 'Mommoo'); map.set('age' , 'secret'); set.add('Mommoo'); set.add('secret'); for ( let item of map ) { console.log(item[0] +' , '+ item[1]); } // name , Mommoo // age , secret for ( let item of set ) { console.log(item); } // Mommoo // secret | cs |
TypeScript는 조금 까다롭습니다. 이유는 Iterable 속성 때문인데요. type iterable 속성때문에 for.. of가 컴파일이 되질 않습니다.
컴파일이 되지 않는 이유를 알고 싶으신 분은 다음 링크 2개를 참고해주세요.
https://stackoverflow.com/questions/37699320/iterating-over-typescript-map
위의 JavaScript와 같이 사용하고 싶다면 컴파일러(tsconfig) 속성인 --downlevelIteration 을 켜주셔야 합니다.
아래의 예시는 속성을 키지 않고, 대안으로 ES6(ES2015) Array API인 Array.from API를 사용하여 구현한 예제 입니다.
Array.from : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/from
[ Ex) TypeScript ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | const map = new Map<string, string>(); const set = new Set<string>(); map.set('name', 'Mommoo'); map.set('age' , 'secret'); set.add('Mommoo'); set.add('secret'); for ( let item of Array.from(map) ) { console.log(item[0] +' , '+ item[1]); } // name , Mommoo // age , secret for ( let item of Array.from(set) ) { console.log(item); } // Mommoo // secret | cs |
Iterator로 순회하기
ES2015-Collection인 Map과 Set는 순회가능한 Iterator입니다. ( IterableIterator )
2번째 방법인 For..of는 내부적으로 Iterator 속성을 이용하여 순회하게 됩니다.
이번에는 직접 Iterator 속성을 이용하여 순회하는 방법입니다.
for.. of 와 마찬가지로 continue, break, return 과 같은 루프 기능을 사용 할 수 있습니다.
[ Ex) JavaScript / TypeScript ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // JavaScript const map = new Map(); const set = new Set(); // TypeScript const map = new Map<string, string>(); const set = new Set<string>(); map.set('name', 'Mommoo'); map.set('age' , 'secret'); set.add('Mommoo'); set.add('secret'); const mapIterator = map.entries(); while ( !mapIterator.next().done ) { const [key, value] = mapIterator.next().value; console.log(key +' , ' +value); } // name , Mommoo // age , secret const setIterator = set.entires(); while ( !setIterator.next().done ) { const [value1, value2] = setIterator.next().value; console.log(value1 +' , ' +value2); } // Mommoo , Mommoo // secret , secret | cs |
개별 값으로 순회 하기
지금까지 본것 처럼, ES2015-Collection은 IterableIterator로써, 두개의 값을 가집니다.
Map은 각각 Key와 Value로써, 가치가 매겨지는 반면, Set역시 두개의 값을 가지지만, 두개의 값은 서로 같습니다.
Set이 필요없는 값을 가지고 있는 이유는 상위 개념인 ES2015-Collection의 다형성 관점으로 구현했기 때문입니다.
위의 예제와 같이 entries 메서드를 호출하면 두개의 값을 가진 IterableIterator인 반면,
두개의 값중 개별 값을 가진 IterableIterator를 만들 수 있습니다.
첫번째 값은 keys 메서드로 호출하고, 두번째 값은 values 메서드를 호출하여 IterableIterator 객체를 만든 후,
2번째 방법 ( for.. of ) 또는 3번째 방법 ( iterator )으로 순회하시면 됩니다.
[ Ex) JavaScript / TypeScript ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | // JavaScript const map = new Map(); const set = new Set(); // TypeScript const map = new Map<string, string>(); const set = new Set<string>(); map.set('name', 'Mommoo'); map.set('age' , 'secret'); set.add('Mommoo'); set.add('secret'); // 첫번째 값 ( 키 ) const mapSingleIterator = map.keys(); // 두번째 값 ( 벨류 ) const mapSingleIterator = map.values(); // 첫번째 값 ( 벨류 ) const setSingleIterator = set.keys(); // 두번째 값 ( 벨류 ) const setSingleIterator = set.values(); /** for of 방법 typescript는 Array.from 메서드로 변환 해야함. 2번째 방법 예시 참고 */ for ( let single of mapSingleIterator ) { console.log(single); } // name // age // ---- or ----- // Mommoo // secret for ( let single of setSingleIterator ) { console.log(single); } // Mommoo // secret /** iterator 방법 */ while ( !mapSingleIterator.next().done ) { const single = mapSingleIterator.next().value; console.log(single); } // name or Mommoo // age or secret while ( !setSingleIterator.next().done ) { const single = setSingleIterator.next().value; console.log(single); } // Mommoo // secret | cs |
준비한 내용은 여기까지 입니다.
읽어주셔서 감사합니다.
'JavaScript' 카테고리의 다른 글
[JavaScript] 요소의 절대좌표 상대좌표 구하기. (9) | 2019.01.16 |
---|---|
[JavaScript/TypeScript] 숫자 여부 판단 (1) | 2018.08.03 |
TypeScript에서 JQuery 라이브러리 사용하기. (0) | 2018.01.08 |
제이쿼리로 만드는 이미지 슬라이더(Image-Slider) (1) (1) | 2016.01.20 |
제이쿼리 브라우져 알아내기. (0) | 2016.01.02 |
포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.