여기서 말하는 객체는 key value 쌍을 말한다.
이전까지는 iterator를 사용해서 다뤘다.
객체를 이터러블 프로그래밍으로 다루는 이유는 코드의 가독성, 유지보수성, 확장성을 높이고 데이터를 효율적으로 처리하기 위해서입니다. 이터러블 프로그래밍은 데이터를 순차적으로 처리하거나 변환하는 작업을 선언적으로 표현할 수 있는 기능을 제공합니다. 객체를 이터러블로 다루는 것은 특히 데이터 구조가 복잡하거나 동적으로 처리해야 할 때 유용합니다.
객체와 이터러블의 차이
- 객체(Object):
- 키-값 쌍으로 데이터를 표현.
- 직접적으로 이터레이션(반복)할 수는 없음.
- JavaScript에서는 객체가 기본적으로 이터러블이 아님.
- 이터러블(Iterable):
- 순회 가능한 데이터 구조(예: 배열, 맵, 세트 등).
- for...of와 같은 구문이나 map, filter 같은 함수형 도구로 처리 가능.
1. Object.values
- 설명:
- 객체의 값들만 추출하여 배열로 반환.
- 배열 형태로 반환되므로 이터러블 프로그래밍(map, filter)과 결합하여 사용할 수 있음.
예제1
const obj = { a: 1, b: 2, c: 3 };
// 값만 추출
const values = Object.values(obj);
console.log(values); // [1, 2, 3]
// 값 중 짝수만 필터링
const evenValues = values.filter(value => value % 2 === 0);
console.log(evenValues); // [2]
예제2
const obj1 = { a: 1, b: 2, c: 3 };
L.values = function* (obj) {
for (const k in obj) {
yield obj[k]; // 각 키의 값을 순차적으로 반환
}
};
_.go(
obj1, // 객체 { a: 1, b: 2, c: 3 }
L.values, // 지연 평가로 값만 추출: [1, 2, 3]
L.map(a => a + 10), // 각 값에 10을 더함: [11, 12, 13]
L.take(2), // 앞에서 두 개의 값만 가져옴: [11, 12]
_.reduce((a, b) => a + b), // 합계 계산: 11 + 12 = 23
console.log // 결과 출력: 23
);
L.values는 지연 평가(lazy evaluation)를 사용하여 객체의 값만을 순회(iterate)하는 이터레이터 함수입니다. 객체의 값을 하나씩 순회하면서 yield를 통해 반환하며, 이터러블 프로그래밍 스타일로 데이터를 처리할 수 있도록 지원
2. Object.entries
- 설명:
- 객체의 키-값 쌍을 배열로 반환. [key, value] 형태의 배열로 변환됨.
- 키와 값을 동시에 처리하거나 변환 작업에 유용.
예제1
const obj = { a: 1, b: 2, c: 3 };
// 키-값 쌍 추출
const entries = Object.entries(obj);
console.log(entries); // [['a', 1], ['b', 2], ['c', 3]]
// 값이 짝수인 키만 필터링
const evenEntries = entries.filter(([key, value]) => value % 2 === 0);
console.log(evenEntries); // [['b', 2]]
// 필터링한 키-값을 다시 객체로 변환
const filteredObj = Object.fromEntries(evenEntries);
console.log(filteredObj); // { b: 2 }
예제2
L.entries = function* (obj) {
for (const k in obj) {
yield [k, obj[k]]; // 객체의 키-값 쌍을 순차적으로 반환
}
};
_.go(
obj1, // { a: 1, b: 2, c: 3 }
L.entries, // 키-값 쌍 이터레이터 반환: ['a', 1], ['b', 2], ['c', 3]
L.filter(([_, v]) => v % 2), // 값이 홀수인 항목만 필터링
L.map(([k, v]) => ({ [k]: v })), // 필터링된 항목을 객체로 변환
_.reduce(Object.assign), // 객체 병합
console.log // 최종 결과 출력
);
결과 출력: { a: 1, c: 3 }.
L.entries는 객체의 키-값 쌍을 지연 평가(lazy evaluation)로 반환하는 이터레이터 함수입니다.
기본적으로 Object.entries와 비슷한 기능을 제공하지만, 지연 평가를 통해 효율성을 극대화하며, 이터러블 프로그래밍에 사용할 수 있습니다.
3. Object.keys
- 설명:
- 객체의 키만 추출하여 배열로 반환.
- 키 이름으로 작업할 때 유용.
예제1
const obj = { a: 1, b: 2, c: 3 };
// 키만 추출
const keys = Object.keys(obj);
console.log(keys); // ['a', 'b', 'c']
// 키가 'b'로 시작하는 항목 필터링
const filteredKeys = keys.filter(key => key.startsWith('b'));
console.log(filteredKeys); // ['b']
예제2
L.keys = function* (obj) {
for (const k in obj) {
yield k; // 객체의 각 키를 하나씩 반환
}
};
_.go(
obj1, // 초기 객체
L.keys, // 객체의 키를 지연 평가로 반환
_.each(console.log) // 반환된 각 키를 `console.log`로 출력
);
L.keys는 객체의 키를 지연 평가(lazy evaluation)로 반환하는 이터레이터 함수입니다.
기본적으로 Object.keys와 비슷한 기능을 제공하지만, 지연 평가를 통해 효율성을 극대화하며, 이터러블 프로그래밍에 사용할 수 있습니다.
4. Object 생성
- 설명:
- 이터러블 데이터를 객체로 변환.
- 배열이나 키-값 쌍(entries)을 객체로 만들 때 사용.
예제1
const entries = [['a', 1], ['b', 2], ['c', 3]];
// 배열을 객체로 변환
const obj = Object.fromEntries(entries);
console.log(obj); // { a: 1, b: 2, c: 3 }
5. mapObject
- 설명:
- 객체의 각 키-값 쌍을 변환.
- Lodash 또는 유사한 라이브러리를 사용하거나 직접 구현 가능.
예제
const obj = { a: 1, b: 2, c: 3 };
// 키-값 변환
const mapped = Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key.toUpperCase(), value * 2])
);
console.log(mapped); // { A: 2, B: 4, C: 6 }
6. pick
- 설명:
- 특정 키를 가진 값들만 추출.
- Lodash 또는 유사한 라이브러리를 사용하거나 직접 구현 가능.
예제
const obj = { a: 1, b: 2, c: 3 };
// 특정 키만 추출
const pick = (obj, keys) =>
Object.fromEntries(Object.entries(obj).filter(([key]) => keys.includes(key)));
const picked = pick(obj, ['a', 'c']);
console.log(picked); // { a: 1, c: 3 }
7. indexBy
- 설명:
- 배열의 값을 기준으로 객체를 생성.
- 배열의 특정 값(또는 속성)을 키로 사용해 객체로 변환.
예제
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
// id를 기준으로 객체로 변환
const indexedById = users.reduce((acc, user) => {
acc[user.id] = user;
return acc;
}, {});
console.log(indexedById);
// {
// 1: { id: 1, name: 'Alice' },
// 2: { id: 2, name: 'Bob' },
// 3: { id: 3, name: 'Charlie' }
// }
8. indexBy 된 값을 filter 하기
- 설명:
- indexBy로 생성된 객체를 필터링.
- 객체를 배열로 변환한 뒤 filter를 적용.
예제
// 위에서 만든 indexedById 객체
const indexedById = {
1: { id: 1, name: 'Alice' },
2: { id: 2, name: 'Bob' },
3: { id: 3, name: 'Charlie' },
};
// 이름이 'A'로 시작하는 사용자만 필터링
const filtered = Object.values(indexedById).filter(user => user.name.startsWith('A'));
console.log(filtered); // [{ id: 1, name: 'Alice' }]
9. 어떠한 값이든 이터러블 프로그래밍으로 다루기
- 설명:
- 이터러블 프로그래밍의 기본 원칙을 적용해 객체, 배열, 또는 기타 데이터를 선언적으로 처리.
예제
const data = {
users: [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 },
],
};
// 이름만 추출
const names = data.users.map(user => user.name);
console.log(names); // ['Alice', 'Bob', 'Charlie']
// 나이가 30 이상인 사용자만 추출
const olderUsers = data.users.filter(user => user.age >= 30);
console.log(olderUsers);
// [{ id: 2, name: 'Bob', age: 30 }, { id: 3, name: 'Charlie', age: 35 }]
// 특정 사용자 객체로 변환
const indexedByName = data.users.reduce((acc, user) => {
acc[user.name] = user;
return acc;
}, {});
console.log(indexedByName);
// {
// Alice: { id: 1, name: 'Alice', age: 25 },
// Bob: { id: 2, name: 'Bob', age: 30 },
// Charlie: { id: 3, name: 'Charlie', age: 35 }
// }
'개발일지 > JavaScript ES6' 카테고리의 다른 글
[21~22] range와 take의 재해석 / takeWile, takeUntil (0) | 2024.12.02 |
---|---|
[18~20] Map, Set / Model, Collection 클래스 / Product, Products / (0) | 2024.12.02 |
[15~16] map으로 합성하기, find 대신 L.filter 써보기 (0) | 2024.11.30 |
[12~14] query, queryToObject (0) | 2024.11.30 |
[10~11] reduce를 사용해 코드 간단하게 만드는 방법 (1) | 2024.11.30 |