728x90
반응형
Javascript의 배열은 객체다
Javascript 배열 요소 안에 key-value 값이나 함수를 설정해도 입력이 잘되는 것을 확인할 수 있다.
const arr = [1, 2, 3];
arr[4] = 'test';
arr['property'] = 'value';
arr['obj'] = {};
arr['{}'] = [1, 2, 3];
arr['func'] = function () {
return 'hello';
};
호출해보면 key-value, 함수 모두 입력되어 있으며
console.log(arr);
// output
[
0: 1
1: 2
2: 3
4: "test"
func: ƒ ()
obj: {}
property: "value"
{}: (3) [1, 2, 3]
length: 5
[[Prototype]]: Array(0)
]
심지어 배열을 객체처럼 메소드 호출도 가능하다.
console.log(arr.func()); // 'hello'
Array.length
Javascript 배열은 객체처럼 동작을 하기 때문에 length를 명시적으로 할당 가능하다.
Aarray.length의 의미는 배열의 길이보다는 배열의 마지막 인덱스라고 보는 것이 맞다.
따라서 Array.length는 배열의 길이를 보장할 수 없으며 원소들이 연속적으로 위치하지 않으며 일부가 비어 있을 수 있다.
예제
예제 1) 원소 개수보다 큰 length 길이 할당
const arr = [1, 2, 3];
console.log(arr.length);
console.log(arr);
arr.length = 10;
console.log(arr.length);
console.log(arr);
// 결과
3
(3) [1, 2, 3]
10
(10) [1, 2, 3, empty × 7]
예제 2) 원소 개수보다 작은 length 길이 할당
const arr = [1, 2, 3];
console.log(arr.length);
console.log(arr);
// 길이보다 큰 나머지 배열 요소들이 지워진다.
arr.length = 1;
console.log(arr.length);
console.log(arr);
// 0으로 설정하여 배열을 초기화가 가능하다.
arr.length = 0;
console.log(arr.length);
console.log(arr);
// 결과
3
(3) [1, 2, 3]
1
[1]
0
[]
배열 요소에 접근하기
배열을 인덱스로 접근해보자
// 배열 인덱스로 접근해보기
const arr = [1, 2, 3];
console.log(arr[0], arr[1]); // 1 2
문제가 되는건 없다. 다만 가독성이 떨어질 뿐이다. arr[0], arr[1]만 보았을 때는 값이 무슨 의미인지 모른다.
그렇기 때문에 구조분해할당을 사용하여 가독성을 높이자는 것이다.
구조분해할당이 무엇인지만 알면 아래 예제들은 이해하기 쉬울 것이다.
변수명을 주어서 구조분해하면 변수명만 봐도 first, second가 무엇인지 가독성이 높아진다.
const [first, second] = [1, 2, 3];
console.log(first, second); // 1 2
유사 배열 객체
- length 속성과 인덱스된 요소를 가진를 배열이 아닌 객체를 말한다.
- 유사배열객체를 Array.from 함수를 사용하여 배열로 변환이 가능하다.
const arrLikeObj = {
0: 'HELLO',
1: 'WORLD',
length: 2
};
console.log(arrLikeObj);
console.log(Array.isArray(arrLikeObj));
const arr = Array.from(arrLikeObj);
console.log(arr);
console.log(Array.isArray(arr));
=
// 결과
{0: 'HELLO', 1: 'WORLD', length: 2}
false
(2) ['HELLO', 'WORLD']
true
불변성 (얕은복사 vs 깊은복사)
쉽게 이야기하면 얕은복사는 메모리상에서 주소만 복사하는 것이고 깊은복사는 새로운 주소로 값을 복사하는 것을 말한다.
얕은복사
- 할당 : 단순 변수에 할당하면 1-depth부터 얕은 복사된다.
const originArr = [1, 2, 3];
const newArr = originArr;
originArr.push(4);
originArr.push(5);
originArr.push(6);
originArr.unshift(0);
console.log(newArr);
// 결과
(7) [0, 1, 2, 3, 4, 5, 6]
- 전개 구문(spread operator) : 1-depth까지는 깊은 복사가 되지만 2-depth 부터 얕은 복사된다.
const originArr = [1, 2, 3, ['가']];
const newArr = [...originArr];
originArr[1] = 'new';
originArr[3][0] = ['나'];
console.log(originArr);
console.log(newArr);
// originArr 결과
(4) [1, 'new', 3, Array(1)]
[
0: 1
1: "new"
2: 3
3: Array(1)
0: ['나']
length: 1
]
// newArr 결과
(4) [1, 'new', 3, Array(1)]
[
0: 1
1: 2
2: 3
3: Array(1)
0: ['나']
length: 1
]
깊은복사
- 재귀적 호출 : 전개 구문 (spread operator) 또는 slice() 메서드를 depth만큼 여러번 또는 재귀적으로 사용한다.
- JSON.parse(JSON.stringify()) : 사용하는 방법이 있는데 데이터 타입(함수, 정규표현식 등)이 지원되지 않으며, 해당 메소드 자체가 재귀 로직이여서 성능이 좋지 않을 수 있는 점을 고려할 필요가 있다.
const originArr = [1, 2, 3, ['가']];
const newArr = JSON.parse(JSON.stringify(originArr));
originArr[1] = 'new';
originArr[3][0] = ['나'];
console.log(originArr);
console.log(newArr);
// originArr 결과
(4) [1, 'new', 3, Array(1)]
[
0: 1
1: "new"
2: 3
3: Array(1)
0: ['나']
length: 1
]
// newArr 결과
(4) [1, 'new', 3, Array(1)]
[
0: 1
1: 2
2: 3
3: Array(1)
0: ['가']
length: 1
]
- 라이브러리 사용(lodash의 cloneDeep 등)
728x90
반응형
'프런트엔드 > 클린코드' 카테고리의 다른 글
JavaScript - 함수 다루기 (0) | 2022.04.18 |
---|---|
JavaScript - 객체 다루기 (0) | 2022.04.15 |
JavaScript - 분기 다루기 (0) | 2022.04.14 |
JavaScript - 경계 다루기 (0) | 2022.04.14 |
JavaScript - 타입 다루기 (0) | 2022.04.14 |