자바스크립트 E6(ES2015)가 나오면서, 편리한 자료구조인 ES2015-Collections( Map, Set )가 등장했습니다.


자바스크립트의 MapSet의 API가 타 언어에 비해 조금 다르더라도, 


타 언어와 많이 다르지 않기 때문에 사용하는것이 어렵진 않습니다.


다만, 순회하는 방법이 조금 독특하기 때문에 이번 포스팅을 하게 되었습니다.



forEach 메서드로 순회하기


Map, Set에서의 forEach( [Map or Set].prototype.forEach )는 ArrayforEach( 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 문법을 사용하면, 가능합니다.


Mapfor.. of로 호출되는 값은 벨류가 들어가 있는 배열 입니다.


Setfor.. 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개를 참고해주세요.

http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#new---downleveliteration

https://stackoverflow.com/questions/37699320/iterating-over-typescript-map


위의 JavaScript와 같이 사용하고 싶다면 컴파일러(tsconfig) 속성인 --downlevelIteration 을 켜주셔야 합니다.


아래의 예시는 속성을 키지 않고, 대안으로 ES6(ES2015) Array APIArray.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인 MapSet는 순회가능한 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은 각각 KeyValue로써, 가치가 매겨지는 반면, 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




준비한 내용은 여기까지 입니다.


읽어주셔서 감사합니다.



포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee


보통 JavaScript에서 숫자 여부를 판단할때 많이 쓰이는 방법은 아래와 같습니다.


1
2
3
4
5
6
7
8
9
isNaN(100)     // false;
isNaN('100px'// true;
 
function isNumeric(data) {
  return !isNaN(data);
}
 
isNumeric(100)   // true;
isNumeric('str'// false;


NaN은 숫자가 될수 없는 문자열을 숫자로 만들때 발생하는데요. ex) ( Number( '100px' ) );


isNaN 함수는 NaN 값인지 아닌지의 여부를 알려주는 함수 입니다.


이로인해 isNaN 함수로 숫자를 판별 할 수 있습니다.


하지만, Type 엄격한 TypeScript에서의 isNaN 함수는 인자로 number 타입만을 받습니다.


string 데이터를 넣지 못하니.. 자바스크립트 처럼 isNaN 함수로만, 숫자 여부를 판단할 수 없습니다.


어떻게 하면 될까요? 정답은 Number 함수를 사용하면 됩니다.


Number 함수에 인자로 string을 넣었을시, 무조건 number 타입으로 리턴이 됩니다.


변환이 가능한 string값은 숫자 값이 올바르게 파싱되지만,


변환이 불가능한 string 값은 NaN이라는 number 타입으로 리턴이 됩니다.


이 개념을 가지고 아래와 같이 메서드로 작성할 수 있습니다..!



1
2
3
4
5
6
7
8
9
Number(100)     // 100;
Number('100px'// NaN;
 
public isNumeric(data : string) : boolean {
  return !isNaN(Number(string));
}
 
isNumeric('100')   // true;
isNumeric('100px'// false;
cs


포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

본 "개인정보 처리 방침"은 "Mommoo"가 배포하는 "안드로이드 어플리케이션"(이하 "앱") 사용을 위하여 요청하는 "민감한 권한" 및 "사용자 정보"에 대한 관리 및 운영에 관한 내용입니다.


1. 사용하는 "민감한 권한" 및 "사용자 정보"와 이의 이용 목적

  1) android.perimission.READ_CONTACTS 
    과기DAY가 "앱"에서 사용자가 등록한 캘린더의 정보를 보여주기 위하여 사용
     

2. "민감한 권한" 및 "사용자 정보"에 대한 수집

해당 과기DAY "앱"을 사용함에 있어 서비스의 이용 내역을 포함한 어떠한 개인 정보도 "Mommoo"가 운영/관리하는 서버로의 수집/전송/저장 하지 않습니다.


3. "민감한 권한" 및 "사용자 정보"에 대한 제3자 제공 및 위탁

"과기DAY" 에서는 정보 이용 목적의 범위를 넘어 사용하거나 제3자에게 제공 또는 위탁하지 않습니다.


4. 기타

본 "개인정보 처리 방침"은 2018년 05월 01일부터 시행됩니다.


'과기DAY > Notice' 카테고리의 다른 글

과기DAY - 2.0v 업데이트  (2) 2016.11.06
과기DAY - 1.7v 업데이트  (0) 2016.07.03
과기DAY - 1.5v 업데이트  (4) 2016.05.16

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee


오늘 포스팅 할 Angular 내용은 ngIf 디렉티브 와 ElementRef 상관관계에 대해서 다룹니다.




왜 ngIf 와 ElementRef 조합일까요?


ngIf 디렉티브를 사용하면, html element를 동적으로 추가/삭제를 구현하기가 편리합니다. 


무엇보다도, 가독성이 떨어지는 DOM API를 사용하는것 이 아닌, 직관적인 코드를 제공하는것이 큰 장점입니다.


하지만, DOM API를 피할 수 없는 순간도 존재합니다.


Angular는 DOM API를 ElementRef 라는 객체를 통해서 제공합니다. 


ElementRef는 HTML Element를 내부적으로 감싼 객체인데, 

보통 ViwChild 어노테이션이나, ViewChildren 어노테이션으로 참조합니다.


문제는 여기서 발생합니다.


ngIf 로 추가/삭제를 하는 HTML Element를 ElementRef 로 받았을 시,

ngIf 로 인한 추가/삭제 와 해당 ElementRef 를 참조하는것이 싱크가 되지 않는다.



해결 방법은?


다행히도, Angular가 제공해주는 API가 있습니다. 


ngIf와 ElementRef 의 싱크를 맞춰주기 위해 필요한 객체는 ChangeDetectorRef 입니다.


아래와 같이 TypeScript 생성자 문법으로 받아 올 수 있습니다. ( 컴포넌트 코드 안에서 작성하였습니다. )


받아 온 후, 싱크를 맞춰야할 메서드 안에서 detectChanges 메서드를 호출하면 됩니다.


1
2
3
4
5
6
7
8
9
10
11
constructor(private changeDetector : ChangeDetectorRef) {
    
}
 
//싱크를 맞추시고 싶은 곳에서
 
public click() : void {
  ...
  this.changeDetector.detectChanges();
  ...
}
cs




끝으로


프레임워크의 장점이자 단점은, 정해진 규칙과 틀을 이용해 개발을 한다는 점입니다.


가이드가 정확히 제시된 것들은 정말 빨리 배울수 있지만, 구현사항이 디테일 할 때 해당 프레임워크의 


이해도가 없다면 프레임워크를 직접 부딪히고 테스트 해봐야 할 것들이 많습니다.


특히 Angular 같이 아직 자료가 많이 없을시엔 더더욱 그렇습니다.


비슷한 이슈로 자료를 찾는 분에게, 본 포스팅으로 도움이 되셨으면 합니다.


감사합니다.

'Angular' 카테고리의 다른 글

Angular Context-Path 설정하기.  (2) 2018.04.04

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

+ Recent posts