const emptyArr = [];
//존재하지 않는 요소에 접근하면 undefined를 반환
console.log(emptyArr[1]); // undefined
console.log(typeof emptyArr); // object
배열 리터럴은 객체 리터럴과 달리 프로퍼티명이 없고 각 요소의 값만이 존재
객체는 프로퍼티 값에 접근하기 위해 대괄호 표기법 또는 마침표 표기법을 사용하며 프로퍼티명을 키로 사용
배열은 요소에 접근하기 위해 대괄호 표기법만을 사용하며 대괄호 내에 접근하고자 하는 요소의 인덱스를 넣어줌
두 객체의 근본적 차이는 배열 리터럴 arr의 프로토타입 객체는 Array.prototype이지만 객체 리터럴 obj의 프로토타입 객체는 Object.prototype이라는 것
대부분의 프로그래밍 언어에서 배열의 요소들은 모두 같은 데이터 타입이어야 하지만, 자바스크립트 배열은 어떤 데이터 타입의 조합이라도 포함 가능
const misc = [
'string',
10,
true,
null,
undefined,
NaN,
Infinity,
['nested array'],
{ object: true },
function () {}
];
Array() 생성자 함수
매개변수가 1개이고 숫자인 경우 매개변수로 전달된 숫자를 length 값으로 가지는 빈 배열을 생성
const arr = new Array(2);
console.log(arr); // (2) [empty × 2]
그 외의 경우 매개변수로 전달된 값들을 요소로 가지는 배열을 생성
const arr = new Array(1, 2, 3);
console.log(arr); // [1, 2, 3]
배열 요소 추가 - 순서에 맞게 값을 할당할 필요는 없고 인덱스를 사용하여 필요한 위치에 값을 할당
const arr = [];
arr[1] = 1;
arr[3] = 3;
console.log(arr); // (4) [empty, 1, empty, 3]
console.log(arr.lenth); // 4
// 값이 할당되지 않은 인덱스 위치의 요소는 생성되지 않는다.
console.log(Object.keys(arr)); // [ '1', '3' ]
// arr[0]이 undefined를 반환한 이유는 존재하지 않는 프로퍼티에 접근했을 때 undefined를 반환하는 것과 같은 이치다.
console.log(arr[0]); // undefined
배열 요소 삭제 - 배열은 객체이기 때문에 배열의 요소를 삭제하기 위해 delete 연산자를 사용 가능
이때 length에는 변함 X
해당 요소를 완전히 삭제하여 length에도 반영되게 하기 위해서는 Array.splice 메소드 사용
onst numbersArr = ['zero', 'one', 'two', 'three'];
// 요소의 값만 삭제된다
delete numbersArr[2]; // (4) ["zero", "one", empty, "three"]
// 요소 값만이 아니라 요소를 완전히 삭제한다
// splice(시작 인덱스, 삭제할 요소 수)
numbersArr.splice(2, 1); // (3) ["zero", "one", "three"]
console.log(numbersArr);
배열은 객체이므로 for…in 문을 사용 O
그러나 배열은 객체이기 때문에 프로퍼티를 가질 수 있음
for…in 문을 사용하면 배열 요소뿐만 아니라 불필요한 프로퍼티까지 출력될 수 있고 요소들의 순서를 보장하지 않으므로 배열을 순회하는데 적합 X
배열의 순회에는 forEach 메소드, for 문, for…of 문을 사용하는 것이 좋음
const arr = [0, 1, 2, 3];
arr.foo = 10;
for (const key in arr) {
console.log('key: ' + key, 'value: ' + arr[key]);
}
// key: 0 value: 0
// key: 1 value: 1
// key: 2 value: 2
// key: 3 value: 3
// key: foo value: 10 => 불필요한 프로퍼티까지 출력
arr.forEach((item, index) => console.log(index, item));
for (const item of arr) {
console.log(item);
}
Array.length
const arr = [1, 2, 3, 4, 5];
console.log(arr.length); // 5
arr[4294967294] = 100;
console.log(arr.length); // 4294967295
console.log(arr); // (4294967295) [1, 2, 3, 4, 5, empty × 4294967289, 100]
배열 요소의 개수와 length 프로퍼티의 값이 반드시 일치 X(=희소 배열)
length 프로퍼티의 값은 명시적으로 변경 O
만약 length 프로퍼티의 값을 현재보다 작게 변경하면 변경된 length 프로퍼티의 값보다 크거나 같은 인덱스에 해당하는 요소는 모두 삭제
const arr = [ 1, 2, 3, 4, 5 ];
// 배열 길이의 명시적 변경
arr.length = 3;
console.log(arr); // (3) [1, 2, 3]
Array Method
1. Array.isArray() - 주어진 인수가 배열이면 true, 배열이 아니면 false를 반환
2. Array.from - 유사 배열 객체 또는 이터러블 객체를 변환하여 새로운 배열을 생성
// 문자열은 이터러블이다.
const arr1 = Array.from('Hello');
console.log(arr1); // [ 'H', 'e', 'l', 'l', 'o' ]
// 유사 배열 객체를 새로운 배열을 변환하여 반환한다.
const arr2 = Array.from({ length: 2, 0: 'a', 1: 'b' });
console.log(arr2); // [ 'a', 'b' ]
// Array.from의 두번째 매개변수에게 배열의 모든 요소에 대해 호출할 함수를 전달할 수 있다.
// 이 함수는 첫번째 매개변수에게 전달된 인수로 생성된 배열의 모든 요소를 인수로 전달받아 호출된다.
const arr3 = Array.from({ length: 5 }, function (v, i) { return i; });
console.log(arr3); // [ 0, 1, 2, 3, 4 ]
// 전달된 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.
const arr1 = Array.of(1);
console.log(arr1); // // [1]
const arr3 = Array.of('string');
console.log(arr3); // 'string'
const arr = [1, 2, 2, 3];
// 배열 arr에서 요소 2를 검색하여 첫번째 인덱스를 반환
arr.indexOf(2); // -> 1
// 배열 arr에서 요소 4가 없으므로 -1을 반환
arr.indexOf(4); // -1
// 두번째 인수는 검색을 시작할 인덱스이다. 두번째 인수를 생략하면 처음부터 검색한다.
arr.indexOf(2, 2); // 2
Array.includes 메소드를 사용하면 보다 가독성이 좋음
ex) if (foods.indexOf('orange') === -1) 대신
if (!foods.includes('orange'))
5. Array.concat(배열 또는 값) - 인수로 전달된 값들(배열 또는 값)을 원본 배열의 마지막 요소로 추가한 새로운 배열을 반환
인수로 전달한 값이 배열인 경우, 배열을 해체하여 새로운 배열의 요소로 추가
원본 배열은 변경 X
const arr1 = [1, 2];
const arr2 = [3, 4];
// 숫자를 원본 배열 arr1의 마지막 요소로 추가한 새로운 배열을 반환
result = arr1.concat(3);
console.log(result); // ["1, 2, 3]
// 배열 arr2와 숫자를 원본 배열 arr1의 마지막 요소로 추가한 새로운 배열을 반환
result = arr1.concat(arr2, 5);
console.log(result); // [1, 2, 3, 4, 5]
const arr = [1, 2, 3, 4];
// 기본 구분자는 ','이다.
// 원본 배열 arr의 모든 요소를 문자열로 변환한 후, 기본 구분자 ','로 연결한 문자열을 반환
let result = arr.join();
console.log(result); // '1,2,3,4';
// 원본 배열 arr의 모든 요소를 문자열로 변환한 후, 빈문자열로 연결한 문자열을 반환
result = arr.join('');
console.log(result); // '1234'
const arr = [1, 2];
// 인수로 전달받은 모든 값을 원본 배열의 마지막에 요소로 추가하고 변경된 length 값을 반환한다.
let result = arr.push(3, 4);
console.log(result); // 4
push 메소드와 concat 메소드의 미묘한 차이
const arr1 = [1, 2];
// 인수로 전달받은 배열을 그대로 원본 배열의 마지막 요소로 추가한다
arr1.push([3, 4]);
console.log(arr1); // [1, 2, [3, 4]]
const arr2 = [1, 2];
// 인수로 전달받은 배열을 해체하여 새로운 배열의 마지막 요소로 추가한다
const result = arr2.concat([3, 4]);
console.log(result); // [1, 2, 3, 4]
const arr = [1, 2, 3];
// 원본 배열 arr의 새로운 복사본을 생성한다.
const copy = arr.slice();
console.log(copy, copy === arr); // [ 1, 2, 3 ] false
원본 배열의 각 요소를 얕은 복사하여 새로운 복사본을 생성
const todos = [
{ id: 1, content: 'HTML', completed: false }
];
// shallow copy
const _todos = todos.slice();
console.log(_todos === todos); // false
// 배열의 요소는 같다. 즉, 얕은 복사되었다.
console.log(_todos[0] === todos[0]); // true
const items1 = [1, 2, 3, 4];
// items[1]부터 2개의 요소를 제거하고 제거된 요소를 배열로 반환
const res1 = items1.splice(1, 2);
// 원본 배열이 변경된다.
console.log(items1); // [ 1, 4 ]
// 제거한 요소가 배열로 반환된다.
console.log(res1); // [ 2, 3 ]
const items = [1, 2, 3, 4];
// items[1]부터 2개의 요소를 제거하고 그자리에 새로운 요소를 추가한다. 제거된 요소가 반환된다.
const res = items.splice(1, 2, 20, 30);
// 원본 배열이 변경된다.
console.log(items); // [ 1, 20, 30, 4 ]
// 제거한 요소가 배열로 반환된다.
console.log(res); // [ 2, 3 ]