본문 바로가기

기술들/javascript

[공부했던 것 정리] 배열의 불변성, 가변성[2]

그렇다면, 원본을 훼손시키지 않는 방법에는 무엇이 있을까? 

상식적으로 원본을 복사하면 된다. 복사본을 삶아 먹든 구워먹든 원본은 그대로 있다. 

 

 

다만 1편에서 예시로 다뤘던 것처럼 복사본에 원본을 직접 할당하면 안된다. 

ex) 원본 : let array1 = [1,2,3];

    복사본: let array2 = array1; (X)

그 이유는 두 배열의 값 모두 같은 메모리에 하나의 값으로 존재하기 때문에 array2의 배열의 값을 

수정하면 당연히 메모리에 하나밖에 없는 배열값이 수정되기 때문에 자동적으로 array1의 배열값(원본)도 수정되기 때문이다. 

 

 

내가 지금껏 배운 선에서 원본을 훼손시키지 않고 복사하는 넘버원 방법은 slice 메소드를 쓰는 것이다. 

slice의 뜻은 '일부분'이다. 어떠한 배열에서 내가 원하는 일부분을 다시 배열로 만드는 것이다. 

 

 

slice메소드의 구동방식을 간단히 설명하면 

[배열].slice(start index, end index)로 사용할 수 있다. 

start index 부터 end index의 element '앞'까지 자를 수 있다는 뜻이다. 

!!여기서 중요한 것은 end index의 element는 포함되지 않는 다는 것이다. 

 

 

백설(?)이 불여일견, 예시를 보겠다. 

let arr1 = ["a","b","c","d","e"];

이 arr1의 "c"부터 "e"까지의 element를 배열로 다시 만들고 싶다면 (원하는 것 :["c","d","e"])

 

 

배열요소 "c"은 index 값이 2 => star index : 2

배열요소 "e"를 포함시키기 때문에 그 뒤에 index 5를 적용시켜줘야 한다.

arr1.slice(2,5); // ["c","d","e"]

["c","d","e"] 배열이 만들어진다. 

 

 

간편하게 arr1.slice(2)이라고 하면 index 2부터 뒤에 나머지 index의 모든 요소가 포함된다. 

arr1.slice(2) // ["c","d","e"]

 

 

다만, 여기서 포인트!는 arr1의 값은 변하지 않는다. arr1의 값은 여전히  ["a","b","c","d","e"];이다. 

console.log(arr1);//  ["a","b","c","d","e"];

원본이 변하지 않는다.

 

 

그렇다면 arr1의 배열값(원본)을 복사본에 할당해보자.

let arr2 =  arr1.slice(); //  (그냥 slice()를 하면 arr1의 모든 요소를 포함시킨다)

console.log(arr2); //  ["a","b","c","d","e"];

 

 

이 때 arr1과 arr2값은 메모리의 다른 위치에 저장되기 때문에 같은 값이 아니다.

Boolean(arr1 === arr2); // false

 

 

그러므로 복사본 arr2의 배열을 수정 변경시켜도 arr1은 변하지 않는다. 

 

 

누군가 "그냥 let arr2 = ["a","b","c","d","e"]라고 정의 해버리면 되지 않는냐" 라고 물을 수도 있다. 

그렇긴 하지만 배열이 매우 크다면 그걸 일일이 적어서 하기 정의하기엔 너무 귀찮고, 실수가 생길 수 있다.

실수는 곧 에러라고 한다.

 

 

배열에서 원본을 그냥 수정시켜버리는 메소드는 다음과 같다. 

[배열].push(element);    ==>  배열의 마지막에 값을 집어 넣음

[배열].pop();    ==> 배열의 마지막 요소를 삭제함

[배열].unshift(element);   ==> 배열의 첫번째에 값을 집어 넣음

[배열].shift();   ==> 배열의 첫번째 요소를 삭제함

 

이 메소드들은 원본에 적용시키면 원본이 바로 수정되기 때문에 사용시 '주의'가 필요하다. 

 

 

지금껏 설명에서 '불변'의 중요성에서 대해 떠들었다고 볼 수 있는데, 이는 마치 '가변'이 '나쁘다'라고 보일 수 있다. 허나 그렇지 않다. 컴퓨터는 '가변'이 안되는 여러 현실세계의 데이터(대표적으로 종이책?)들을 '가변'을 하기 위해 출현했다고 볼 수 있고, 더 좋은 앱이나 시스템을 개발하기 위해 '가변'은 필수이다. 즉, '가변'은 성장을 위한 디지털의 특권이라고도 볼 수 있다. 그렇지만 꼭 불변하게 존재해야 하는 데이터들도 꽤 많이 존재하기 때문에 이에 대해 설명하였다.

 

 

추가적으로, 

배열엔 원본 전체를 자동적으로 복사해서 그 값을 한꺼번에 수정까지 하여 '배열'이나 어떠한 '값'으로 반환하는 '메소드'들이 존재한다.

filter , map, forEach, reduce등이 그것들이다. 이를 설명하기엔 아직 나도 배우고 있는 부분이라 쉽지 않을 것 같다. 이후에 완전히 숙달이 된다면 이 메소드들에 대해 포스팅 하겠다.