3. 자바스크립트 데이터 타입과 연산자 #5 배열

2021. 7. 21. 15:37JavaScript/basic

본 글은 인사이드 자바스크립트 도서의 내용을 복습하기 위해 작성된 글입니다.

3.5 배열

자바스크립트 배열의 특징

  1. 크기를 지정하지 않아도 된다.
  2. 각각의 요소의 타입을 동일하게 하지 않아도 된다.

3.5.1 배열 리터럴

배열 리터럴이란?

배열 리터럴은 자바스크립에서 새로운 배열을 만드는 데 사용하는 표기법이다. 겍체 리터럴이 중괄호( { } )를 이용한 표기법이었다면, 배열 리터럴은 대괄호( [] )를  사용한다.

 

배열 리터럴을 통한 배열 생성

// 배열 리터럴을 통한 5개 원소를 가진 배열 생성
let colorArr = ["orange", 'yellow', 'blue', 'green', 'red'];
console.log(colorArr[0]);   // orange
console.log(colorArr[1]);   // yellow
console.log(colorArr[4]);   // red

객체가 프로퍼티의 이름으로 대괄호나 마침표 교비버을 이용해서 해당 프로퍼티에 접근했다면, 배열의 경우는 위 처럼 대괄호 내에 접근하고자 하는 원소에 배열 내 위치 인덱스값을 넣어서 접근한다. 배열 내의 첫번째 원소는 인덱스 0부터 시작한다.

 

3.5.2 배열의 요소 생성

자바스크립트 배열은 동적으로 배열 원소를 추가할 수 있다. 특히 값을 순차적으로 넣을 필요 없이 아무 인덱스 위치에나 값을 동적으로 추가할 수 있다.

 

배열 요소의 동적 생성

// 빈 배열
let emptyArr = [];
console.log(emptyArr[0]);   // undefined

// 배열 요소 동적 생성
emptyArr[0] = 100;
emptyArr[3] = "eight";
emptyArr[7] = true;

console.log(emptyArr); // [100, empty, empty, "eight", empty, empty, empty, true]

console.log(emptyArr.length);   // 8

자바스크립트 배열의 크기는 현재 배열의 인덱스 중 가장 큰값을 기준으로 정한다. 따라서 emtpyArr 배열이 실제로 3개의 요소만이 채워져 있더라도 길이는 8이된다.

 

3.5.3 배열의 length 프로퍼티

자바스크립트의 모든 배열은 length 프로퍼티가 존재한다. 단, length 프로퍼티는 배열의 원소 개수를 나타내지만, 실제로 배열에 존재하는 원소 개수와 일치하는 것은 아니다. 하지만 length 프로퍼티는 배열 내에 가장 큰 인덱스에 1을 더한 값이다.

 

배열의 length 프로퍼티 변경

let arr = [];
console.log(arr.length);    // 0

arr[0] = 0;         // arr.length = 1
arr[1] = 1;         // arr.length = 2
arr[2] = 2;         // arr.length = 3

arr[100] = 100;     
console.log(arr.length);    // 101

 

배열 length 프로퍼티의 명시적 변경

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

arr.length = 5;
console.log(arr);           // [0, 1, 2, empty, empty]

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

 

3.5.3.1 배열 표준 메서드와 length 프로퍼티

자바스크립트는 배열에서 사용 가능한 다양한 표준 메서드를 제공한다. 이러한 배열 메서드는 length 프로퍼티를 기반으로 동작한다. 대표적으로 push() 메서드가 존재한다. push() 메서드는 배열의 현재 length 값의 위치에 새로운 원소값을 추가한다. 

 

push() 메서드와 length 프로퍼티

// arr 배열 생성
let arr = ["zero", "one", "two"];

// push() 메서드 호출
arr.push("three");
console.log(arr);   // ["zero", "one", " two", "three"]

// length 값 변경 후, push() 메서드 호출
arr.length = 5;
arr.push("four");
console.log(arr); // ["zero", "one", " two", "three", empty, "four"]

 

3.5.4 배열과 객체

자바스크립트에서는 배열 역시 객체이다. 하지만 배열은 일반 객체와는 약간 차이가 존재한다.

 

배열과 객체의 차이점

  1. 배열은 length 프로퍼티를 갖지만 일반 객체는 갖지 않는다.
  2. 배열은 push() 메서드를 사용 할 수 있지만 객체는 사용하지 않는다.
// colorsArray 배열
let colorsArray = ["orange", "yellow", "green"];
console.log(colorsArray[0]);    // orange
console.log(colorsArray[1]);    // yellow
console.log(colorsArray[2]);    // green

// colorsObj 객체
let colorsObj = {
    "0" : "orange",
    "1" : "yellow",
    "2" : "green"
};

console.log(colorsObj[0]);    // orange
console.log(colorsObj[1]);    // yellow
console.log(colorsObj[2]);    // green

// typeof 연산자 비교
console.log(typeof colorsArray);    // object (not array)
console.log(typeof colorsObj);      // object

// length 프로퍼티
console.log(colorsArray.length);    // 3
console.log(colorsObj.length);      // undefined

// 배열 표준 메서드
colorsArray.push("red");    // ["orange", "yellow", "green", "red"]
colorsObj.push("red");      // Uncaught TypeError : colorsObj.push is not a function

객체가 push() 메서드를 사용하지 못하는 이유

객체의 경우 프로토타입이 Object.prototype 객체이다. 그런데 배열의 프로토타입은 Array.prototype 객체이다. 따라서 push() 메서드는 Array.prototype 객체에만 존재하기 때문에 일반적인 객체는 push() 메서드를 사용하지 못한다.

 

객체의 프로토타입과 배열의 프로토타입

배열의 프로토타입과 객체의 프로토타입 비교

let emptyArray = [];
let emptyObj = {};

console.dir(emptyArray.__proto__);
console.dir(emptyObj.__proto__);

 

3.5.5 배열의 프로퍼티 동적 생성

배열도 자바스크립트 객체이므로, 인덱스가 숫자인 배열 원소 이외에도 객체처럼 동적으로 프로퍼티를 추가할 수 있다.

 

배열의 동적 프로퍼티 생성

// 배열 생성
let arr = ["zero", "one", "two"];
console.log(arr.length);    // 3

// 프로퍼티 동적 추가
arr.color = "blue";
arr.name = "number_array";
console.log(arr.length);    // 3

// 배열 원소 추가
arr[3] = "red";
console.log(arr.length);    // 4

// 배열 객체 출력
console.dir(arr); // {"0" : "Zero", "1" : "one", "2" : "two", "3" : "red", 
                  //    "color" : "blue", "name" : "number_array"}

배열의 length 프로퍼티는 배열 원소의 가장 큰 인덱스가 변했을 경우에만 변경된다. 배열에 프로퍼티를 동적으로 추가해도 length 프로퍼티의 값은 변하지 않는다.

 

3.5.6 배열의 프로터 열거

배열의 프로퍼티 열거

프로퍼티까지 전부 출력하고 싶다면 for in 문 사용, 배열의 원소만 출력하고 싶다면 for문 사용

for(let prop in arr){
    console.log(prop, arr[prop]);
}

for(let i=0; i<arr.length; i++){
    console.log(i, arr[i]);
}

3.5.7 배열 요소 삭제

배열도 객체이므로, 배열 요소나 프로퍼티를 삭제하 데 delete 연산자를 사용할 수 있다.

 

delete 연산자를 이용한 배열 프로퍼티 삭제

let arr = ["zero","one","two","three"];
delete arr[2];
console.log(arr);           // ["zero","one", empty,"three"]
console.log(arr.length);    // 4

위의 결과에서 arr[2]에 undefined가 할당되게 된다. 그러나 delete 연산자로 배열 요소 삭제 후에도 배열의 length 값은 변하지 않은 것을 확인 할 수 있다. 즉, delete 연산자는 해당 요소의 값을 undefined로 설정할 뿐 원소 자체를 삭제하지는 않는다. 때문에 보통 배열에서 요소들을 완전히 삭제할 경우 자바스크립트에서는 splice() 배열 메서드를 사용한다.

 

splice() 배열 메서드

splice(start, delteCount, item...)
- start : 배열에서 시작 위치
- deleteCount : start에서 지정한 시작 위치부터 삭제할 요소의 수
- item : 삭제할 위치에 추가할 요소

 

splice() 메서드를 이용한 배열 프로퍼티 삭제

let arr = ["zero","one","two","three"];

arr.splice(2,1);    // 2번째 요소에서 1개의 원소를 제거
console.log(arr);   // ["zero","one","three"]
console.log(arr.length);    // 3

 

3.5.8 Array() 생성자 함수

Array() 생성자 함수를 통한 배열 생성

let foo = new Array(3);
console.log(foo);           // [empty*3]
console.log(foo.length);    // 3

let bar = new Array(1,2,3);
console.log(bar);           // [1,2,3]
console.log(bar.length);    // 3

 

3.5.9 유사 배열 객체

배열의 length 프로퍼티는 배열의 동작에 있어서 중요한 프로퍼티이다. 그런데 만약 일반 객체에 length라는 프로퍼티가 있으면 어떻게 될까? 자바스크립트에서는 이렇게 length 프로퍼티를 가진 객체를 유사 배열 객체라고 부른다.

 

유사 배열 객체의 배열 메서드 호출

let arr = ["bar"];
let obj = {
    name : "foo",
    length : 1
};

arr.push("baz");
console.log(arr);   // ["bar","baz"]

obj.push("baz");    // error

배열 arr은 push() 메소드 사용시 원소를 정상적으로 추가하는 반면 객체 obj는 당연히 배열이 아니므로 push() 메서드 호출시 에러가 발생한다.

하지만 유사 배열 객체의 경우 4장에서 배울 apply() 메서드를 사용하면 객체지만 표준 배열 메서드를 활용하는 것이 가능하다.

 

유사 배열 객체에서 apply()를 활용한 배열 메서드 호출

 let arr = ["bar"];
 let obj = {
     name : "foo",
     length : 1
 };
 
 arr.push("baz");
 console.log(arr);   // ["bar","baz"]
 
 Array.prototype.push.apply(obj, ["baz"]);
 console.log(obj);  // {"1" : "baz", name:"foo", length:2}

 

References

인사이드 자바스크립트, 송형주 저