자바스크립트 코딩의 기술_Collection으로 데이터 관리하기_2

자바스크립트 2021. 5. 23. 16:40

(본 포스팅은 길벗의 '자바스크립트-코딩의 기술' 책을 공부하면서 작성되었습니다_내돈내산)

2021.05.23 - [자바스크립트] - 자바스크립트 코딩의 기술_Collection으로 데이터 관리하기_1

 

자바스크립트 코딩의 기술_Collection으로 데이터 관리하기_1

(본 포스팅은 길벗의 '자바스크립트-코딩의 기술' 책을 공부하면서 작성되었습니다_내돈내산) 1. 객체(Object)를 이용해 정적인 키-값(key-value)를 탐색하라. 원칙적으로 객체는 변화가 없고 구조화

pg-titannia.tistory.com

 

4. 맵으로 명확하게 키-값 데이터를 갱신하라

  • 일반적으로 '키-값 쌍이 자주 추가되거나 삭제되는 경우', '키가 문자열이 아닌경우' 대표적인 두가지 상황에서 객체보다 맵(Map)을 선택하는 것이 더 나은 결과를 가져옴.
  • 객체와 Map 의 정보를 갱신하는데 있어 추가, 삭제, 모든조건제거 이 세가지의 방법이 필요하며, 서로 구현하는 방법도 달라지게 됨.
// 객체를 다룰 때 
let filter = {}; // 객체 선언 및 할당
function addFilters(filters, key, value) {
  filters[key] = value; // 조건추가
}

function deleteFilters(filters, key) {
  delete filters[key];  // 조건 삭제
}

function clearFilters(filters) {
  filters = {}; //  객체 초기화
  return filters;
}

// Map 을 다룰때
let filters = new Map();
const petFilters = new Map();
function addFilters(filters, key, value) {
  filters.set(key, value);  // 조건추가
}

function deleteFilters(filters, key) {
  filters.delete(key); // 조건 삭제
}

function clearFilters(filters) {
  filters.clear();  // 객체 초기화
}
  • 위의 코드에서 볼 수 있듯이 객체의 경우 단순히 중괄호만으로 선언이 가능하며, Map의 경우 생성자를 이용해 생성시켜주어야 한다. 그리고 Map 의 메서드를 이용해 조작이 가능해지게 된다(set(key, value)를 이용해 원소의 갱신 또는 추가가 가능해짐).
  • 또한 Map의 경우 키값이 제한되지 않는다. 객체의 경우 키값이 문자로만 제한되지만 Map 의 경우 정수타입의 데이터도 키값으로 활용이 가능하다. (객체는 정수를 사용한 경우 전부 문자열로 치환되어 저장되어짐.
// Map 의 주요한 메서드
let filters = new Map() // 맵 선언
filters.set('key', 'value') // 맵에 데이터 추가
filters.get('key') // 'key'에 해당하는 value 반환
filters.delete('key') // 'key'에 해당하는 key-value 쌍 삭제
filters.clear() // 맵컬렉션 초기화(새로운 인스턴스 생성 필요 없음)

5. 맵과 펼침 연산자로 키-값 데이터를 순회하라.

  • 키-값 컬렉션에 항목을 자주 추가하거나 삭제하는 경우는 객체보다 맵을 사용하는 것이 적합하다.
  • 객체는 순회하기가 매우 번거롭고, 순회하기 위해서는 변환하는 작업이 필요하다. for... in문을 사용할 수 있지만, 객체 키 외에는 접근방법이 없음.
  • 맵은 직접 순회가 가능하다.
// 객체 순환 방법
const filters = {
  color: 'black',
  breed: 'labrador',
};

function getAppliedFilters(filters) {
  const keys = Object.keys(filters);
  const applied = [];
  for (const key of keys) {
    applied.push(`${key}:${filters[key]}`);
  }
  return `Your filters are: ${applied.join(', ')}.`;
}

// Yout filters are color:black, breed:labrador
  1. Object.keys( )를 이용해서 객체의 일부를 배열로 옮긴다.
  2. for문으로 키를 순회한다.
  3. for문을 실행하는 동안 객체를 참조해 값을 꺼낸다.
  4. 필터링 조건을 정렬하기 위해서는 먼저 키를 정렬해야 함(객체에서 순서가 보장되지 못함)
// 맵 이터레이터 사용
const filters = new Map()
  .set('color', 'black')
  .set('breed', 'labrador');

function checkFilters(filters) {
  for (const entry of filters) {
    console.log(entry);
  }
}
// ['color', 'black']
// ['breed', 'labrador'

// entries( ) 메서드
filters.entries( );
// MapIterator{ ['색상', '검정색'], ['견종', '레브라도리트리버'] }

function getAppliedFilters(filters) {
  const applied = [];
  for (const [key, value] of filters) {
    applied.push(`${key}:${value}`);
  }
  return `Your filters are: ${applied.join(', ')}.`;
}
// 'Your filters are: color:black, breed:labrador.'
  1. 몇가지 값을 동시에 넘겨줌. 
  2. 이터레이터는 키-값 쌍을 넘겨줌.
  3. 위와같은 코드를 entries( )라는 메서드를 이용해 맵 이터레이터를 반환하게 할 수 있음.
  4. 결과적으로 훨씬 단순하면서도 원래의 데이터 구조를 유지하는 코드를 작성할 수 있음.
  5. 맨 아래에 있는 getAppliedFilters함수를 보았을때, Map 객체 자체는 iterator로 키-값쌍을 배열로 반환하기 때문에 가능한 코드 작성법이다.
  • 맵에서도 펼침연산자를 사용함에 따라 정렬문제를 해결할 수 있다. 맵자체가 순서를 저장하기는 하지만 배열처럼 정렬메서드가 내장되어있지않게 됨. filter.sort( )와같은 방법으로 정렬이 불가능하다.
[...filter];
// [['color', 'black'], ['breed', 'labrador']]

function sortByKey(a, b) {
  return a[0] > b[0] ? 1 : -1;
}

function getSortedAppliedFilters(filters) {
  const applied = [];
  for (const [key, value] of [...filters].sort(sortByKey)) {
    applied.push(`${key}:${value}`);
  }
  return `Your filters are: ${applied.join(', ')}.`;
}
// 'Your filters are: breed:labrador, color:black.'

// 맵객체에 펼침연산자를 사용하여 sort( ) 함수를 적용시킨 사례
function getSortedAppliedFilters(filters) {
  const applied = [...filters]
    .sort(sortByKey)
    .map(([key, value]) => {
      return `${key}:${value}`;
    })
    .join(', ');

  return `Your filters are: ${applied}.`;
}
// 'Your filters are: breed:labrador, color:black.'
  • 이전에 생성한 맵객체를 배열안에 펼쳐넣는 순간 맵객체를 배열로 변환이 가능하며, 이를 통해 내부 배열에 정렬메서드를 적용시킬 수 있게 된다.
  • 맵객체에 펼침연산자를 적용시켜 배열화 시킨 후 sort( ) 메서드를 적용시키면 배열을 순회하게 되고, 배열의 map( ) 메서드를 이용해 원하는 작업을 진행할 수 있음.

6. 맵 생성 시 부수 효과를 피하라.

  • 맵의 인스턴스를 이용해 작업할때 맵의 사본생성, 부수효과 등을 피하면서 맵을 변경하는 것이 중요함. 
  • 두가지 맵 객체를 서로 합칠 때, 그러니까 기본 맵에 다른 맵객체를 덮어씌울때 맵의 사본을 만드는 작업을 통해 진행이 가능하다.
function applyDefaults(map, defaults) {
  const copy = new Map([...map]);
  for (const [key, value] of defaults) {
    if (!copy.has(key)) {
      copy.set(key, value);
    }
  }
  return copy;
}
  • 위의 코드처럼 펼친연산자를 이용해 배열안에 map 객체를 펼쳐놓음으로써 원하는 맵 객체의 사본을 생성시킬 수 있다. 필터링 조건의 사본을 생성하였고, 여기에 기본값을 적용했다. 이런식의 코딩을 함으로써 원본 기본값은 변경되지 않지만 사용자가 원하는 값을 가진 Map 객체를 생성하였다.
  • 다른 방안으로는 맵이 하나의 키를 한번만 사용할 수 있는 성질을 이용한다. 즉, 새로운 키로 맵을 생성하면 어떤 값이든 해당 키에 마지막으로 선언한 값을 사용하게 됨.
  • 위의 코드를 아래와같이 심플하게 고칠 수 있다(펼침연산자와 Map 의 기본성질을 사용)
function applyDefaults(map, defaults) {
  return new Map([...defaults, ...map]);
}

7. 세트를 이용해 고윳값을 관리하라.

  • 세트(Set)은 고유항목을 하나씩만 갖는 특화된 배열과 같다.
  • 맵과 유사하지만, 세트의 새로운 인스턴스는 중첩하지 않은 배열을 인수로 받는다는데 있다.
// 기본적인 Set 객체 생성법
const color = ['검정색', '검정색', '갈색'];
const unique = new Set(colors); // Set {'검정색', '갈색'}

// 펼침연산자를 이용한 리팩토링
function getUnique(attributes) {
	return [...new Set(attributes)];
}
  • 위와같이 중복된 값을 제거하고 고유한 요소만 포함하는 Set 객체를 생성할 수 있으며, 변수에 할당하는 과정 없이 인스턴스를 생성하자 마자 펼침연산자를 이용이 가능하다.
  • 세트의 경우 값을 추가할때는 add( ) 메서드를, 검증할 때는 has( ) 메서드를 사용한다. 또한, 세트에도 맵처럼 delete( )와 clear( ) 메서드가 있다.
  • 세트에 항목을 추가할 때는 배열에 한번에 담아 전달할 수 잇지만, 반복문을 이용해 개별적으로 추가가 가능하다.
  • 세트는 고유값을 가지는 컬렉션타입이기 때문에 세트에 없는 값은 추가할 수 있으며, 이미 세트에 존재하는 값을 추가할경우 자동적으로 무시된다.(이미 존재하는 값을 다시 넣더라도 원래값의 위치는 유지되어짐.)
admin