배열

2019. 7. 17. 17:57javascript

배열은 자바스크립트 객체의 특별한 형태이다. 크기를 지정하지 않아도 되고 어떤 위치에 어느 타입의 데이터를 저장하더라도 에러가 발생하지 않는다.

 

1. 배열 리터럴

배열 리터럴은 새로운 배열을 만드는 데 사용하는 표기법으로 대괄호([])를 사용한다.

var colorArr = ["orange", "yellow", "blue", "green", "red"];

console.log(colorArr[0]) // orange
console.log(colorArr[3]) // green

객체 리터털에서는 프로퍼티 이름과 프로퍼티 값을 모두 표기해야 하지만 배열 리터럴에서는 각 요소의 값만을 포함한다.

객체의 경우는 프로퍼티의 이름으로 해당 프로퍼티에 접근했다면 배열의 경우 배열 내 인덱스 값으로 접근한다.

 

2.배열의 요소 생성

배열도 객체와 마찬가지로 원소를 추가할 수 있고 값을 순차적으로 넣을 필요 없이 아무 인덱스 위치에나 값을 동적으로 추가할 수 있다.

var emptyArr = [];
console.log(emptyArr[0]); // undefined

emptyArr[0] = 100;
emptyArr[3] = "eight"
emptyArr[7] = true;

console.log(emptyArr); // [100, undefined x 2, "eught", undefined x 3, true]
console.log(emptyArr.length); // 8

emptyArr [0] 값에 접근하였을 때 undefined가 나오는 이유는 배열 또한 객체이기 때문에 객체에서 포함하지 않는 프로퍼티에 접근할 경우 undefined가 출력되는 것과 같다.

 

emptyArr에 100,"eight",true 3개의 값을 저장했지만 출력할 경우 8개의 요소 값이 출력된다. 이것은 자바스크립트가 배열의 크기를 현재 배열의 인덱스 중 가장 큰 값을 기준으로 정하기 때문이다. 값이 할당 되지 않은 요소는 undefined값을 기본으로 가진다.

 

3. 배열의 length 프로퍼티 

자바스크립트의 모든 배열은 length 프로퍼티가 있다. length 프로퍼티는 배열의 원소 개수를 나타내지만 실제 배열에 존재하는 원소 개수와 일치하는 것은 아니다. 위에서 보았듯이 요소의 값은 3개이지만 length 값은 8이 출력된다. 즉 length 프로퍼티는 배열 내에서 가장 큰 인덱스에 1을 더한 값이다. 

 

var 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 값이 늘어나는 것을 확인할 수 있다. 인덱스 100위 치에 값을 저장했을 때  length가 101로 늘어나지만 length크기처럼 실제로 메모리 값이 할당되진 않는다.

 

배열의 length 프로퍼티는 코드를 통해 명시적으로 값을 변경할 수 있다.

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

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

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

 

  1. 배열 표준 메서드  

자바스크립트는 배열에서 사용 가능한 다양한 표준 메서드를 제공한다. 이러한 메서드는 length 프로퍼티를 기반으로 동작하고 있다. 

push()는 현재 배열의 끝에 추가하는 메서드로 length 값의 위치에 새로운 원소값을 추가한다.

 

var arr = ["zero", "one", "two"]

arr.push("three");
console.log(arr); // ["zero", "one", "two", "three"]

arr.length = 5;
arr.push("four");
console.log(arr); // ["zero", "one", "two", "three", undefined, "four]

 

4.배열과 객체

배열 역시 객체이지만 약간의 차이가 있다. 

// 배열
var colorsArray = ["orange", "yellow", "green"]
console.log(colorArray[0]); // orange
console.log(colorArray[1]); // yellow
console.log(colorArray[2]); // green

//객체
var 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
console.log(typeof colorsObj); // object

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

// push
colorsArray.push("red"); // ["orange", "yellow", "green", "red"]
colorsObj.push("red"); // Uncaught TypeError: object .......

앞서 객체 프로퍼티에 접근을 할 때 프로퍼티의 속성을 문자열로 적어야 한다고 했지만 colorsObj[0]의 형태로 기입하여도 출력이 되고 있다. 그 이유는 자바스크립트 엔진이 [] 연산자 내에 숫자가 사용될 경우 자동으로 문자열 형태로 바꿔주기 때문이다.

 

1) length 프로퍼티의 존재 여부 

 colorsObj는 객체 이므로 length 프로퍼티가 존재하지 않는다. 그래서 undefined가 나오는 것이다.

 

2) 배열 표준 메서드 호출 여부

 객체 리터럴 방식으로 생성한 객체의 경우 Object.prototype(객체 표준 메서드를 저장하고 있다.) 객체가 프로토타입이다.

배열의 경우 Array.prototype(배열 표준 메서드를 저장하고 있다.) 객체가 프로토 타입이다. 

그래서 colorsObj.push()를 실행할 경우 자신의 프로토타입 객체가 다르기 때문에 에러가 발생한다.

 

3) Array.prototype 객체의 프로토 타입은 Object.prototype 객체가 된다.

 객체는 자신의 프로토 타입이 가지는 모든 프로퍼티 및 메서드들을 상속받아 사용할 수 있으므로 배열은 Array.prototype 와 Object.prototype의 표준 메서드를 모두 사용할 수 있다.

 

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

 

Object.prototype                         Object.prototype                      

          ↑                                       ↑

          객체 (__proto__)                   Array.prototype (__proto__)

                                                   ↑

                                                              배열 (__proto__)

 

var emptyArray = []; //	배열 리터럴로 빈 배열 생성
var emptyObj = {}; // 객체 리터럴로 빈 객체 생성

console.dir(emptyArray.__proto__); // 배열의 프로토타입(Array.prototype) 
console.dir(emptyObj.__proto__); // 객체의 프로토타입(Object.prototype)

5. 배열 프로퍼티 동적 생성

var 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);

arr에 동적으로 color와 name 프로퍼티를 추가했지만 배열의 길이는 변하지 않는다. 배열의 length프로퍼티는 배열 원소의 가장 큰 인덱스가 변했을 경우만 변경되기 때문이다.

console.dir(arr)로 출력한 arr의 프로퍼티를 보면 배열도 객체처럼 "key : value" 형태로 원소 및 프로퍼티 등이 있음을 알 수 있다. 

 

6. 배열의 프로퍼티 열거

var arr =["zero", "one", "two", "red", color: "blue", name: "number_array"]

for(var prop in arr){
	console.log(prop. arr[prop]);
}
*/0 zero
  1 one
  2 two
  3 red
  color blue
  name number_array/*



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

*/0 "zero"
  1 "one"
  2 "two"
  3 "red"/*

for in 문으로 출력을 했을땐 color와 name 프로퍼티 까지 출력된 반면 for 문은 정확히배열의 요소만을 출력하고 있다.

(for in 문으로 배열내의 프로퍼티를 열거할 수 있지만 불필요한 프로퍼티가 출력될 수 있으므로 되도록 for문을 사용하는 것이 좋다.)

 

7. 배열 요소 삭제 

delete를 사용할 수 있다.

var arr = ["zero", "one", "two", "three"];
delete arr[2];
console.log(arr); // ["zero", "one", undefined x 1. "three]
console.log(arr.length) // 4

delete로 배열의 요소를 삭제하면 undefined가 할당된다. 

length값이 변하지 않는 것을 볼 수 있다. 즉 delete연산자가 해당 요소를 undefined로 설정할 뿐이지 원소 자체를 삭제하지 않는다.

때문에 요소들을 완전히 삭제할 경우 splice() 메서드를 사용한다.

※splice(start, deleteCount, item...)

  •  start - 배열에서 시작 위치
  • deleteCount - start에서 지정한 시작 위치부터 삭제할 요소의 수
  • item - 삭제할 위치에 추가할 요소

8. Array() 생성자 함수

Array() 생성자 함수는 호출할 때 인자개수에 따라 동작이 다르므로 주의해야 한다.

  • 호출할 때 인자가 1개이고, 숫자일 경우 : 호출된 인자를 length로 갖는 빈 배열 생성
  • 그외의 경우 : 호출된 인자를 요소로 갖는 배열 생성
var foo = new Array(3);
console.log(foo); // [undefined, undefined, undefined]
console.log(foo.length); // 3

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

 

9.유사 배열 객체

length 프로퍼티를 가진 객체를 유사 배열 객체라고 부른다. 

유사배열의 큰 특징은 객체임에도 불구하고, 배열 메서드를 사용하는게 가능하다는 것이다.

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

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

obj.push("baz") // error

위의 예제 처럼 유사 배열 객체 obj는 배열이 아니므로 에러가 발생한다. 하지만 apply() 메서드를 사용하면 배열 메서드를 사용하는 것이 가능하다. 

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

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

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

 

'javascript' 카테고리의 다른 글

Prototype, __proto__, constructor 의 관계  (0) 2019.07.29
함수 객체  (0) 2019.07.19
함수  (0) 2019.07.18
객체  (0) 2019.07.15
자바스크립트 데이터 타입  (0) 2019.07.14