songin.dev님의 블로그

자바스크립트 프로토타입, 배열 본문

Developer/Langauge

자바스크립트 프로토타입, 배열

songin.dev 2022. 7. 11. 22:15
728x90

프로토타입

자바스크립트의 모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있다.

이것은 마치 객체지향의 상속 개념과 같이 부모 객체의 프로퍼티를 마치 자신의 것처럼 쓸 수 있는 것 같은 특징이 있다.

자바스크립트에서는 이러한 부모 객체를 프로토타입 객체(프로토타입)이라고 부른다.

// 객체 생성 및 출력

var foo = {
  name: 'foo',
  age: 30
};

console.log(foo.toString()); // [object Object]

console.dir(foo); // Object

앞 예제에서 생성한 foo 객체는 toString() 메서드가 없으므로 에러가 발생해야 하지만, 정상적으로 결과가 출력된다. 그 이유는

foo 객체의 프로토타입에 toString() 메서드가 이미 정의되어 있고, foo 객체가 상속처럼 toString() 메서드를 호출했기 때문이다.

객체 리터럴로 생성한 name과 age 프로퍼티 이외에도 foo 객체에  __proto__ 프로퍼티가 있다.

이 프로퍼티가 앞서 설명한 foo객체의 부모인 프로토타입 객체를 가리킨다. 이 객체의 다음 부분에 toString() 메서드가 정의되어 있고, 이 때문에 앞 예제에서 오류 없이 제대로 출력된 것이다.

자바스크립트의 모든 객체는 자신의 프로토타입을 가리키는 [[Prototype]]이라는 숨겨진 프로퍼티를 가진다.

객체 리터럴 방식으로 생성된 객체의 경우 Object.prototype 객체가 프로토타입 객체가 된다는 것만 일단 기억하자!

 

배열

배열은 자바스크립트 객체의 특별한 형태다.

크기를 지정하지 않아도 되며, 어떤 위치에 어느 타입의 데이터를 저장하더라도 에러가 발생하지 않는다.

 

배열 리터럴

배열 리터럴은 자바스크립트에서 새로운 배열을 만드는 데 사용하는 표기법이다. 

배열 리터럴은 대괄호[ ]를 사용한다.

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

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

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

 

배열의 요소 생성

자바스크립트 배열의 경우는 값을 순차적으로 넣을 필요 없이 아무 인덱스 위치에나 값을 동적으로 추가할 수 있다.

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

// 배열 요소 동적 생성
emptyArr[0] = 100;
emptyArr[3] = 'eight';
emptyArr[7] = true;
console.log(emptyArr); // [100, undefined*2, 'eight', undefined*3, true]
console.log(emptyArr.length); // 8

값이 있는 배열의 값이 7이므로, 배열의 length를 출력하게 되면 8이 출력된다.

인덱스가 가장 큰 값을 기준으로 그 안에 있는 인덱스 중 값이 비어있는 요소는 undefined의 값을 갖게 된다.

 

배열의 length 프로퍼티

자바스크립트의 모든 배열은 length 프로퍼티가 있다.

length 프로퍼티는 배열 내에 가장 큰 인덱스에 1을 더한 값이다.

때문에 배열의 가장 큰 인덱스값이 변하면, length 값 또한 자동으로 변경된다.

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

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

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

// 배열 length 프로퍼티의 명시적 변경
var arr = [0, 1, 2];
console.log(arr.length); // 3

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

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

배열의 length의 값을 임의로 수정하게 되면, 비어있는 요소는 undefined가 되며, 값이 있는 요소가 length 값보다 큰 경우 삭제된다.

 

배열과 객체

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

// colorsObj 객체
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

// 배열 표준 메서드
colorsArray.push('red'); // ['orange', 'yellow', 'green', 'red'];
colorsObj.push('red'); // Uncaught TypeError: Object #<Object> has no method 'push'

배열과 유사하게 객체 리터럴 방식으로 생성했고, 결괏값 역시 비슷하게 출력되었다.

객체의 대괄호 안에는 접근하려는 프로퍼티의 속성을 문자열 형태로 나타내야 하는데, 정상적인 결과가 실행된 이유는 자바스크립트의 엔진이 대괄호 연산자 내에 숫자가 사용될 경우, 해당 숫자를 자동으로 문자열 형태로 바꿔주기 때문에 그렇다.

typeof 연산 결과는 배열과 객체 모두 object 이지만, length 프로퍼티와 push() 메서드 등은 배열이 아닌 객체에서는 사용할 수 없다.

 

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

배열의 프로퍼티 동적 생성

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

// 배열 생성
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

배열의 length 프로퍼티는 배열 원소의 가장 큰 인덱스가 변했을 경우만 변경된다.

결국 배열도 객체처럼 'key: value' 형태로 배열 원소 및 프로퍼티 등이 있음을 알 수 있다.

 

배열의 프로퍼티 열거

// 배열의 프로퍼티 열거

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 문은 0에서 3까지 배열 요소들을 포함해서, color와 name 프로퍼티까지 출력된 반면, for문은 정확히 배열의 요소만을 출력하고 있다.

 

배열 요소 삭제

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

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

delete 연산자는 해당 요소의 값을 undefined로 설정할 뿐 원소 자체를 삭제하지는 않는다.

배열에서 요소들을 완전히 삭제할 경우 자바스크립트에서는 splice() 배열 메서드를 사용한다.

splice() 배열 메서드
splice(start, deleteCount, item..)
start - 배열에서 시작 위치
deleteCount - start 위치부터 삭제할 요소
item - 삭제할 위치에 추가할 요소

Array() 생성자 함수

배열은 일반적으로 배열 리터럴로 생성하지만, 배열 리터럴도 결국 자바스크립트 기본 제공 Array() 생성자 함수로 배열을 생성하는 과정을 단순화시킨 것이다.

생성자 함수로 배열과 같은 객체를 생성할 때는 반드시 new 연산자를 같이 써야 한다.

// Array() 생성자 함수를 통한 배열 생성
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

유사 배열 객체

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

하지만, apply() 메서드를 사용하면 객체지만 표준 배열 메서드를 활용하는 것이 가능하다.

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

var arr = ['bar'];
var 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 }

- 본 포스팅은 "인사이드 자바스크립트" 도서를 기반으로 작성한 글입니다.

반응형
Comments