-배열
자바스크립트의 배열은 C의 배열과는 조금 다르다.
오히려 파이썬의 리스트에 더까운데, 그렇다고 파이썬의 리스트와 완전히 같은 것도 아니다.
배열의 생성은 배열 리터럴이나 생성자 함수를 이용한다.
배열 리터럴은 [] 를 이용하여 표기한다. 파이썬과 똑같다.
var a = ['apple', 10, true];
위와 같이 데이터 형이 통일 되지 않아도 된다.
배열 요소에 접근하여 읽고 쓸 때도, 배열 내 위치 인덱스 값을 이용해 [] 로 접근한다.
a[0] = 'orange';
console.log(a[0]);
// orange
여기까지는 파이썬의 리스트와 다를 게 없어보인다.
그러나 자바스크립트 배열의 특이한 점은 배열에 동적으로 값을 넣을 때, 인덱스를 신경쓰지 않고 넣을 수 있다는 점이다.
var b = [];
b[1] = 10;
console.log(b);
// [empty x 1, 10]
이렇게 배열 사이즈 밖에 있는 값을 쓰려고 해도 오류없이 써지며, 그 값 이전의 빈 공간은 모두 empty 로 표기된다.
(책에서는 undefined x n 형태로 표기된다고 나와있지만, 실제로 크롬으로 돌려보니 다르게 나왔다.
undefined x n 형태로 되어 있으면 임의로 'undefined' 값을 넣은 것과 헷갈릴 여지가 있어 수정된 게 아닐까 추측해본다.
생성자 함수를 이용해 생성할 때는 다음과 같다.
var array = new Array(3); // 길이가 3인 빈 배열 생성, (empty x 3)
var array2 = new Array(1,2,3); // [1, 2, 3] 인 배열
인자로 숫자 한개를 받을 땐, 해당 숫자 길이의 빈 배열을 만들어내고,
다른 타입이 들어오면 해당 타입이 들어있는 배열을 생성한다.
-배열의 length 프로퍼티
자바스크립트 배열의 length 프로퍼티는 특수하다.
이 length 프로퍼티의 값은 '배열의 가장 큰 인덱스 값 + 1' 이다.
내가 실제로 빈 배열에 몇개의 값을 넣었든지, 그 횟수는 중요한게 아니다.
한 개의 값을 넣었더라도 인덱스 100의 위치에 넣었다면, 배열의 length 프로퍼티값은 101이다.
나머지 빈 공간은 empty x 100 으로 채워졌을 것이다.
하지만 실제로 메모리는 101의 사이즈가 아니라 내가 넣은 단 하나의 값 만큼만 할당된다.
이는 역으로 length프로퍼티 값을 쓸 때도 적용된다.
내가 배열에 0부터 순차적으로 5개의 값을 넣고, 임의로 배열의 length 값을 2로 줄인다면, 인덱스 2~4 의 배열 값은 삭제되어 접근해도 undefined가 나오게 된다. (가려져서 없는 것처럼 보이는게 아니라 메모리에서 실제로 사라진다.)
사진에서 볼 수 있듯이, length를 조작하여 값을 날리고, 다시 length 를 늘리면 비어있는 공간이 생기게 된다.
원래의 값이 복구되지 않는다.
반대로 배열에 아무 값을 넣지 않은 상태에서 length 프로퍼티를 임의로 5로 늘리면, empty x 5 로 표기된다.
물론 메모리에는 아무런 값도 할당되어 있지 않다.
- 배열에 값 넣기
배열에 값을 넣을 때는 인덱스로 직접 값을 넣거나 push 메소드를 이용할 수 있다.
push 메소드를 이용하는 경우, 현재 길이 (length 프로퍼티 값)에 해당하는 인덱스에 값을 넣고, 길이를 1 늘린다.
이렇게 동작하기 때문에 임의로 배열의 길이가 조절되는 경우, 배열에 push 메소드로 값을 추가할 때 추가되는 위치가 바뀐다.
배열에 인덱스로 직접 값을 넣어 생성하는 경우, 해당 인덱스가 기존 length 프로퍼티 값보다 크지 않다면 배열의 length 프로퍼티 값은 변하지 않는다.
또한 배열도 객체이므로 동적으로 임의 프로퍼티를 넣어줄 수 있는데, 프로퍼티를 넣는 것은 배열의 길이에 영향을 주지 않는다.
원소 추가와 프로퍼티 추가는 구분되어 동작한다고 이해하면 된다.
그렇다면 과연 배열 객체는 0 과 '0'을 구분할 수 있을까?
아쉽게도 구분은 하지 못한다. 배열도 객체이기 때문인걸까. 문자열 형태로 숫자를 만들어 넣어도 원소가 추가된다.
- 배열과 객체
배열도 객체이다. 하지만 지난 번에 만들었던 일반 리터럴 객체와 완전히 같지는 않다.
배열은 Array.prototype 을 프로토타입으로 상속받는 객체로서, length 프로퍼티를 가지고 push 와 같은 메소드를 갖는다.
또한 일반 배열은 원소에 접근할 때 [ ] 에 '문자' 를 넣어야 하지만, 배열은 숫자로도 접근이 가능하다.
(일반 배열도 숫자를 넣어서 접근할 수 있지만, 내부적으로 이를 ToString() 함수를 이용해 문자열로 바꿔서 사용한다.)
- 배열의 프로퍼티 열거
배열도 객체이므로 for in 문으로 프로퍼티를 열거 할 수 있지만, 배열도 객체인지라 원소 이외의 프로퍼티가 같이 출력될 수 있다.
따라서 원소만을 출력할 때는 단순 for 문을 이용하여 열거하는 것이 좋다.
한가지 신기한점은 for in 문으로 열거를 하더라도 배열의 length 프로퍼티는 출력되지 않는다는 점이 흥미롭다.
그래도 안전하게 단순 for 문을 사용해서 열거하는게 좋겠다.
- 배열 원소 삭제
배열의 원소를 삭제하는 경우 원소도 프로퍼티이므로 delete 연산자를 이용해 삭제할 수 있다.
삭제된 원소는 빈 공간이 되며, length 프로퍼티를 임의로 조작했을 때와 마찬가지로 'empty' 로 표기된다.
(사진은 한국어로 번역된 상태라 '비어 있음' 으로 표기된다.)
그러나 이렇게 delete 명령어로 원소를 삭제하더라도, 배열의 length 프로퍼티 값은 변하지 않았다.
책에서 delete 연산자는 해당 요소의 값을 undefined로 설정할 뿐 원소 자체를 삭제하지 않는다. 라고 표현하고 있는데,
이는 조금 헷갈리는 표현 같기도 하다. 원소를 삭제하지 않는다고 하면, 마치 메모리도 여전히 할당되어 있는 것처럼 느껴질 수도 있겠다.
하지만 length 프로퍼티의 값이 변하지 않은 이유는, 아까도 말했듯 가장 큰 인덱스의 값 + 1 이 length 프로퍼티의 값이기 때문에 변하지 않은 것이 아닐까? 가장 큰 인덱스를 삭제하면 어떻게 될까?
정말로 length 프로퍼티의 값이 변하지 않았다.
하지만 책과 다른 점은 undefined 값으로 설정해서 넣는 대신 '비어 있음' 처리를 해버리고 있다.
그렇다면 비어있음 처리가 아니라 정말 아예 완전히 지워버리는 방법은 없을까?
책에서는 splice() 메소드를 사용하는 방법을 소개하고 있다.
array.splice(start, deleteCount, item ...) : 삭제 시작 위치 , 삭제할 개수, 삭제한 곳에 넣을 item
이 메소드를 이용해 첫번째 원소와 두번째 원소를 지워보면 아래와 같다.
....??? 뭔가 이상하다. 0번째 부터 2개를 지우게 했는데 왜 [1, 2] 가 나왔을까?
거기에 한번더 같은 메서드를 적용하니까 이번엔 기존 배열의 2, 3 번째 인덱스의 값들이 들어있다.
다시 새 배열에다가 메서드를 사용해보았다.
내가 크롬 개발자 도구를 잘못 이해하고 있었다. ㅋㅋㅋ
저 [1, 2] 는 이 splice 메서드의 리턴값이었다. 이걸로 splice() 메서드가 기능을 수행하면서 잘라낸 배열을 리턴한다는 것을 알았다.
실제로 d 를 출력해보니 잘 잘려나간 것을 볼 수 있었다.
- 유사 배열 객체
배열의 push 메서드는 length 프로퍼티를 기준으로 한다는 점에서 배열의 'length' 프로퍼티는 매우 중요하다.
그래서 일반 객체에 'length' 프로퍼티가 있는 경우, 이 객체를 '유사배열객체' 로 부르며, 이 객체는 배열이 아님에도 불구하고
자바스크립트의 표준 배열 메서드를 사용할 수 있다.
사진과 같이, 유사 배열 객체는 push 메소드를 바로 사용할 수 없지만, 나중에 나올 apply 함수를 이용해 표준 배열 메서드를 사용해 원소를 넣을 수 있다. (length 값이 늘어난 것을 볼 수 있다.)
'독서 > Inside Javascript' 카테고리의 다른 글
[Inside Javascript] 7. 함수 생성 (0) | 2022.06.30 |
---|---|
[Inside Javascript] 6. 기본타입과 표준메서드, 연산자 (0) | 2022.06.12 |
[Inside Javascript] 4. 프로토타입 개념 (0) | 2022.04.06 |
[Inside Javascript] 3. 자바스크립트의 객체 (0) | 2022.03.26 |
[Inside Javascript] 2. 자바스크립트의 데이터타입 (0) | 2022.03.25 |