map, mutable, immutable, state

이효범·2022년 4월 3일
1

ES6 - OOP & FRP

목록 보기
2/15
post-thumbnail

Array는 Array Class의 인스턴스이다. 따라서 Array Class에 정의되어 있는 메소드들을 활용할 수 있다. 주인장은 Array의 헬퍼 메소드들을 통해 OOP와 FRP의 기초에 대해 공부해보려 한다.

map

let numbers = [1, 2, 3, 4, 5];
let doubleNumbers = [];

// impelative

// declarative

위의 코드에 적힌 것처럼 doubleNumbers에 numbers의 값들에 2배를 한 값들을 넣어보자.

let numbers = [1, 2, 3, 4, 5];
let doubleNumbers = [];

// impelative = mutable

// declarative = immutable
let doubled = numbers.map(function (number) {
    return number * 2;
});

여기에서 impelative는 mutable라고 부른다.
mutable이라는 것은 변화한다, 변할 수 있는 이라는 뜻을 내포한다.
반대로 immutable는 값이 변하지 않는 것을 뜻한다.

위의 예시는 간단한 예시이기 때문에, mutable과 immutable의 차이는 확연하게 드러나지 않지만, 이는 굉장히 중요한 개념이다.

예를 들어 다음과 같은 코드는 mutable이다.

let i = 1;
i += 1;
i;

위처럼 변수의 값 자체를 변화시키는 것을 mutable라고 한다.

하지만

let doubled = numbers.map(function (number) {
    return number * 2;
});

와 같이 새로운 doubled 라는 값을 리턴하지만, 원래의 numbers 배열 자체에 변화는 없게 하는 것이 immutable 방식이다. 즉 원래의 numbers는 그대로 두고, 그저 numbers를 이용하여 새로 doubled 배열을 만들게 된다. 이를 소위 immutable이라고 말한다.

또한 여기서 state라는 개념 또한 도출이 되는데,

let i = 1;   // i의 state는 1이다.
i += 1;      // i의 state를 변화시킨다.
i;           // 여기서 i의 state는 2가 된다.

위의 코드를 보면서 이해가 되는가? state is a value of a variable at a moment 라고 설명할 수 있다. 즉 어느 한 순간에 어느 변수가 가지고 있는 값이다.

state management는 굉장히 중요한 개념이 되는데, 만약 1억명의 사용자가 numbers = [1, 2, 3, 4, 5]라는 같은 코드를 공유하고 있다고 하자. 그런데 이를 한 개인이 배열의 원소를 마음대로 바꿔버리면 다른 1억명의 사람들은 굉장히 혼란을 겪을 수 있다. 따라서 이를 꼭 바꿔야 한다면 정해진 규칙대로 엄격하게 룰을 적용해서 바꿔야 하거나, 아예 immutable한 방식으로 배열을 이용해야만 어플리케이션의 혼란을 피할 수 있다.
또한 이러한 state management에는 declative의 방식이 훨씬 더 유용하다.

결국 mutable과 immutable, 그리고 state라는 개념을 잘 익혀두는 것이 중요하다.
이를 잘 알고 있어야 나중에 state 관리라는 측면에는 왜 immutable를 사용해야 하며 immutable 방식은 왜 declative의 방식을 사용하게 되는지에 대해서 위의 예제와 설명들을 통해서 기초적인 개념을 정확히 이해해나가야 한다.


map 연습

연습문제이다.
Declarative한 방식, 즉 immutable한 방식으로 다음을 구현하자.

// create a new array including only height of each image.
let images = [
    { height: '34px', width: '39px' },
    { height: '54px', width: '19px' },
    { height: '83px', width: '75px' },
];

let heights;

두번째 연습문제이다.


// create a new array including speed of each item: distance/time
let trips = [
    { distance: 34, time: 10 },
    { distance: 90, time: 50 },
    { distance: 59, time: 25 },
];

let speeds;

첫 번째 연습문제에 대한 코드.

heights = images.map(function(image) {
	return image.height
})
console.log(heights);

두 번째 연습문제에 대한 코드.

speeds = trips.map(function(trip) {
	return trip.distance / trip.time;
})
console.log(speeds)

여기까지 해보니 어떠한가? declarative 방식이 impelative 방식에 비해서 훨씬 더 간명하고 간단하고 편리하다.


Pluck 함수 연습

let heroes = [{ name: 'superman' }, { name: 'batman' }, { name: 'x-man' }];

위 배열에 대해서 다음과 같은 결과값을 출력하는 함수 pluck을 구현한다.

pluck(heroes, 'name'); // returns ['superman', 'batman', 'x-man'];

Impelative한 방식

function pluck(array, property) {
    let answer = [];
    for(let i = 0; i < array.length; i++) {
        answer.push(array[i][property]);
    }
    return answer;
}

Declarative한 방식

1. forEach 사용

function pluck(array, property) {
    let answer = [];
    array.forEach((el) => {
        answer.push(el[property]);
    })
    return answer;
}

2. map 사용

function pluck(array, property) {
    return answer = array.map(function(hero) {
        return hero[property]
    })
}
profile
I'm on Wave, I'm on the Vibe.

0개의 댓글