자바스크립트 완벽 가이드 7판 스터디
책의 목차를 따라가며 관련 내용을 학습하고 공유하는 스터디입니다.

1. 자바스크립트에서 배열(Array)이란?
ㄴ MDN에서는 배열을 아래와 같은 특성을 가진 객체라고 설명한다.
ㄴ 배열의 객체 속성과 배열 요소 목록은 별개이다.
2. Dense Array vs Sparse Array
ㄴ Dense Array (밀집 배열)
ㄴ Sparse Array (성긴 배열)
3. 배열을 생성하는 방법 (feat. I like Array.from)
4. length 프로퍼티로 배열 조작하기
5. 배열요소를 삭제할 때 delete 사용을 지양하자
6. 원본배열을 수정하는 메서드를 조심하자
7. forEach vs for...of, forEach의 동작원리 알아보기
8. 유사배열객체 - HTMLCollection, NodeList, arguments 등


1. 자바스크립트에서 배열(Array)이란?

Array

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

MDN에서는 배열을 아래와 같은 특성을 가진 객체라고 설명한다.

  • 배열은 크기 조정이 가능하며 데이터 유형에 상관 없이 모든 값을 혼합해 포함할 수 있다.
    • 원시값, 함수, 객체, 심볼 등 모두 가능하다.
  • 배열은 음수가 아닌 정수를 Index 로 사용하여 접근해야한다.
    • 문자열 형식으로 접근해도 된다(타입추론). arr['1']
    • Index는 0부터 시작. 마지막 Index는 배열의 length - 1 이다.

배열의 object properties(객체 속성)list of array elements(배열 요소 목록)은 별개이다.

  • 배열은 객체다. 따라서 객체의 처럼 프로퍼티를 추가할 수 있다.
    • 이렇게 추가된 속성은 배열의 요소 목록과 별개로 취급한다.
    • 속성은 배열의 요소 순회로 접근할 수 없다.
    • length 는 배열 요소 목록만을 포함한다.
const arr = [1, 2, 3];
arr['key'] = 'property';
arr[true] = -1;
arr[() => false] = -1;

arr;
// [ 1, 2, 3, key: 'property', true: -1, '() => false': -1 ]
// key : value 형태로 저장된 것을 확인할 수 있다.

arr.length; // 3
// 배열의 요소만 길이에 포함된다.

for (const el of arr) console.info(el); // 1, 2, 3
arr.forEach(el => console.info(el)); // 1, 2, 3
// 1, 2, 3은 배열의 요소 목록이다. 요소만 순회한다.

for (const key in arr) {
  console.info(key);
}
// 0
// 1
// 2
// key
// true
// () => false

// for...in 으로 객체의 키를 조회하면 인덱스와 속성의 키를 확인할 수 있다.

2. Dense Array vs Sparse Array

Sparse Arrays vs Dense Arrays in JavaScript — Explained with Examples

https://www.freecodecamp.org/news/sparse-and-dense-arrays-in-javascript/

Dense Array (밀집 배열)

  • 배열의 요소 개수와 배열의 길이가 정확하게 같다. arr.length === 요소 개수
  • 요소가 인덱스 0에서 시작해 마지막 인덱스까지 모두 순차적으로 있다.
  • 마지막 인덱스는 배열의 길이 - 1이다. arr[length - 1]
const denseArray = [1, 2, 3, 4, 5];

denseArray.length; // 5
denseArray[denseArray.length - 1]; // 5

Sparse Array (성긴 배열)

  • 요소가 순차적이지 않다.
  • 배열의 요소 개수와 배열의 길이가 같지 않다.
  • delete 로 배열의 요소를 지우면 해당 요소가 삭제되고 empty 상태가 된다.
  • forEach, map 등 메소드가 순회할 때 요소가 없는 인덱스는 순회에서 제외된다.
    • 길이가 10, 요소가 5개인 배열을 순회하면 5번만 순회한다.
const sparseArray = [];

sparseArray[10] = 1;
sparseArray[11] = 2;
sparseArray[12] = 3;
sparseArray[13] = 4;
sparseArray[14] = 5;

sparseArray; // [ <10 empty items>, 1, 2, 3, 4, 5 ]
sparseArray.length; // 15
sparseArray[0]; // undefined

3. 배열을 생성하는 방법 (feat. I like Array.from)

배열 리터럴

const arr1 = [1, 2, 3];
arr1; // [1, 2, 3];
arr1.length; // 3

const arr2 = [1, , 3];
arr2; // [ 1, <1 empty item>, 3 ];
arr2.length; // 3

Array 생성자 함수

  • 인수가 없으면 빈배열 생성
  • 인수가 0이상 정수면 length가 인수인 배열 생성
    • 음수면 에러
  • 인수가 2개 이상, 숫자가 아닌 경우 인수를 요소로 갖는 배열 생성
const arr3 = new Array();
arr3; // [];
arr3.length; // 0

const arr4 = new Array(5);
arr4; // [ <5 empty items> ]
arr4.length; // 5

const arr5 = new Array(1, 2, 3, 4, 5);
arr5; // [ 1, 2, 3, 4, 5 ]
arr5.length; // 5

Array.of()

  • ES6에서 추가된 메서드
  • 전달된 인수를 요소로 갖는 배열을 생성
    • Array()의 인수 1개일 경우를 보완
const arr6 = Array.of();
arr6; // [];
arr6.length; // 0

const arr7 = Array.of(5);
arr7; // [ 5 ]
arr7.length; // 1

const arr8 = Array.of(1, 2, 3, 4, 5);
arr8; // [ 1, 2, 3, 4, 5 ]
arr8.length; // 5

Array.from()

  • ES6에서 추가된 메서드
  • 인수로 유사배열객체, 이터러블을 받는다.
  • 인수로 받는 객체가 다양하고 메서드 하나로 다양한 배열을 만들 수 있어서 개인적으로 선호한다.
  • 두번째 인수(Optional)로 콜백 함수를 받아 배열의 요소를 콜백 함수를 통해 만들어서 채울 수 있다.
const arr9 = Array.from('Iterable'); // 이터러블
arr9; // ['I', 't', 'e', 'r', 'a', 'b', 'l', 'e'];
arr9.length; // 8

const arr10 = Array.from({ length: 2, 0: 1, 1: 2 }); //유사배열객체
arr10; // [1, 2]
arr10.length; // 2
  • 주로 유사배열객체의 length 와 콜백 함수를 사용해 배열을 만든다.
  • 유사배열 객체로 length만 전달하면 undefined로 요소를 채운다.
    • 의도적으로 특정 인덱스에 빈 값을 요소로 넣고 배열을 순회하면서 빈 값을 조작하고 싶을 때 사용한다.
// 1부터 n까지를 요소로 갖는 배열 만들기
const n = 5;
const arr11 = Array.from({ length: n }, (_, i) => i + 1);

arr11; // [1, 2, 3, 4, 5]
arr11.length; // 5

// length 만 사용
const arr12 = Array.from({ length: n });
arr12; // [ undefined, undefined, undefined, undefined, undefined ]
arr12.length; // 5

// length만 사용 + 순회하기
const arr13 = Array.from({ length: n }).map((_, i) => i % 2 === 0 && i);
arr13; // [ 0, false, 2, false, 4 ]
arr13.length; // 5

4. length 프로퍼티로 배열 조작하기

  • length 프로퍼티 값은 배열이 업데이트될 때 같이 갱신된다.
  • length 프로퍼티에 직접 숫자 값을 할당하면 length 프로퍼티 값이 할당한 숫자로 변한다.
    • length 값보다 큰 숫자면 길이가 커진 만큼 empty가 늘어난다.
    • length 값보다 작은 숫자면 길이가 작아지고 작아진 만큼 요소가 삭제된다.
const arr = [1, 2, 3];

console.log(arr); // [1, 2, 3]
console.log(arr.length); // 3

arr.length = 5;

console.log(arr); // [1, 2, 3, <2 empty items>]
console.log(arr.length); // 5

arr.length = 2;

console.log(arr); // [1, 2]
console.log(arr.length); // 2

5. 배열요소를 삭제할 때 delete 사용을 지양하자

  • delete연산자로 배열요소를 삭제하면, 성긴배열이 되고 length 값은 변하지 않는다.
  • splice를 사용하면 성긴배열을 만들지 않고 삭제할 수 있다.
const arr = [1, 2, 3];

delete arr[0];

console.log(arr); // [ <1 empty item>, 2, 3 ]
console.log(arr.length); // 3
const arr = [1, 2, 3];

arr.splice(0, 1);

console.log(arr); // [ 2, 3 ]
console.log(arr.length); // 2

6. 원본배열을 수정하는 메서드를 조심하자

  • 원본 배열을 직접 변경하는 메서드는 의도하지않은 사이드이펙트를 발생시킬 수 있어서 조심해야한다.
  • 만약 원본 배열을 직접 변경하지 않을 수 있다면 그 방법을 사용하자.
// 상태 값으로 배열이 있고, 해당 상태값(배열)에 요소가 추가되는 경우

state.push(element);

state = [...state, element]; // 원본 배열을 복사해 사용

7. forEach vs for...of, forEach의 동작원리 알아보기


8. 유사배열객체 - HTMLCollection, NodeList, arguments 등

  • 유사배열객체는 length 프로퍼티를 갖고 객체의 키가 배열의 인덱스처럼 0부터 1씩 증가한다.
  • 유사배열객체는 배열처럼 인덱스로 값에 접근할 수 있지만 배열 메소드를 사용할 수 없다는 큰 단점이 있다.
    • HTMLCollection, NodeList 같은 유사배열객체는 자체적으로 순회할 수 있는 forEach 메서드가 있다. Array의 forEach 메서드와 다르니까 주의.
    • HTMLCollection, NodeListLive 속성 때문에 의도하지 않은 동작이 발생할 수 있다. 그래서 배열로 변환해서 사용하는 것을 추천한다.
let obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  3: 'd',
  length: 4,
};

const arr = Array.from(obj);
console.log(arr); // [ 'a', 'b', 'c', 'd' ]

for...of 로 HTMLCollection을 순회하면서 DOM조작할 때 주의할 점🚨
유사배열객체인 HTMLCollection, NodeList로 돔을 조작하다가 만난 문제를 정리한 글이다.



참고자료

0개의 댓글