Roen의 iOS 개발로그

JavaScript 기초3(Python과 비교하여, ES6 기준) : 배열

by Steady On

📣 이 자료는 ⎡혼자 공부하는 자바스크립트⎦책과 MDN Web docs를 기반으로 작성되었습니다.

그리고 개인적으로 공부하고 이해한 내용을 바탕으로 정리하는 용도로 작성되었으므로 이해를 돕기위한 예시는 최소화하였습니다.

 

3-1. 배열

 

<배열>

배열이란?

JS의 배열은 파이썬의 리스트와는 개념이 완전 다르다. 파이썬의 리스트는 어떤 데이터를 넘버링해서 모아둔 속지를 추가하는 파일같은 느낌이다. 인덱스를 활용해서 데이터를 찾아볼 수도 있고 넣었다가 빼는 것도 자유롭다. 자바스크립트의 배열도 마찬가지이다. 그럼 도대체 뭐가 다를까?

JS의 배열은 객체이고, 그 안에 무한대의 자리(속성)가 있다. 자리는 있고 아직 정의되지 않았을 뿐이다. 그리고 우리가 데이터를 넣으면(그게 어떤 자료형이든) 맨 앞에서부터(0번) 자리에 들어간다. 즉,  우리가 넣은 데이터는 배열의 속성이 되는 것이다. 그럼 여기서 궁금할 수 있다. '아니 속성이면 .속성명으로 콜해야 하는거 아님?' 맞다. 통상적으로는 그렇다. 내가 좋아하는 MDN Web docs의 말을 빌리자면, 

이 현상은 JavaScript 배열과 그 속성에 어떤 특별한 점이 있어서 그런 것이 아닙니다. 모든 JavaScript 속성은 이름이 숫자로 시작할 경우 마침표 표기법으로 접근할 수 없고, 대괄호 표기법을 사용해야 합니다.
- MDN Web docs, Array에 관한 설명중...

이라고 한다. 그래서 얘는 어떻게보면 인덱스 같은 애지, 인덱스는 아니고 속성인 것이다. 그래서 JS의 배열은 진짜 특이한 점이 한가지 더있다. 예를 들어, 파이썬에서 길이가 5인 리스트에서 인덱스가 5 또는 6에 접근하거나 호출을 한다고 생각해보자. 그럼 분명히 IndexError가 뜨면서 out of range라는 메세지가 나올 것이다. 하지만 자바 스크립트는 길이를 넘는 인덱스에 접근하거나 호출해도 에러가 나지 않는다. 대신 그 속성 값이 아직 정의되지 않았기 때문에 undefined만 나올뿐...

마찬가지로 우리가 인덱스로 접근해서 데이터를 추가한다고 생각해보자. 파이썬은 이미 가지고 있는 데이터는 인덱스로 접근하는 것을 허용하지만, 아직 만들어지지 않는 인덱스에 대해서는 칼같이 Error를 띄운다. 예를 들어 길이가 3인 리스트a가 있을 때 a[3] = 3 이라고 하면 IndexError가 뜬다. 반면에 자바스크립트는 어떨까? 길이가 3인 배열 a에 인덱스 10은 10이라고 정의해보자.

let a = [0, 1, 2]
a[10] = 10

console.log(a)
//[ 0, 1, 2, <7 empty items>, 10 ]

이런 결과가 나왔다. 3~9까지의 자리는 비어있고, 10에는 데이터가 잘 들어갔다. 웃기지 않은가?

나는 아까 파이썬의 리스트가 속지를 추가하는 파일 같다고 했다. 자바 스크립트의 배열은 비유하자면 야구 경기장 같다. 이미 좌석은 넘버링 되어서 마련되어 있다. 관객은 자기가 원하는 자리에 앉으면 된다. 가운데가 비어있어도 되고, 멀리 떨어져 앉아도 된다. 리스트에 값을 추가하는 함수의 이름이 파이썬은 append (덧붙이다, 첨부하다)이고, JS는 push (밀다, 누르다)인것도 이 개념과 관련이 있지 않을까? 

 

배열 조작

배열에 값을 추가하는 것은 위에서 언급했고, 그럼 인덱스를 통해 값을 찾고, 없애고, 중간에 값을 넣는 방법을 알아보자. 먼저, 리스트의 일정 인덱스 범위를 가지고 오고 싶을때, 파이썬의 경우 인덱스 하는 것과 비슷하게 대괄호를 사용해서 슬라이싱 해오면 된다. a[3:6](리스트 a에서 인덱스 3이상, 6미만의 요소를 가져오겠다는 뜻) 이렇게! 그런데 자바 스크립트는 slice라는 메소드를 사용해야 한다.

 

❗️slice 메소드

이름 : slice

메소드 : 배열

매개변수 : 시작 인덱스, (종료 인덱스; 입력하지 않으면 끝까지)

리턴 값(타입) : 배열의 시작 인덱스 이상, 종료 인덱스 미만의 범위를 얕게 복사하여 리턴(배열)

파괴여부 : 비파괴

 

그럼 중간 인덱스의 요소를 삭제하거나 오히려 추가하고 싶으면 어떻게 해야할까? 파이썬의 경우 요소 삭제는 del을 사용한다. (remove메소드도 있지만, 그건 인덱스가 아니라 값을 이용하는 것이므로 논외). 삭제하고자 하는 요소의 인덱스나 슬라이싱 범위를 설정해서 del 키워드를 앞에 써주면 된다. 중간에 특정 인덱스에 값을 추가하는 것은 insert 메소드를 사용한다. 그럼 JS는 어떻게 할까? 

 

❗️splice 메소드

이름 : splice

메소드 : 배열

매개변수 : 시작 인덱스, (제거할 요소의 수, 배열에 추가할 요소(여러개)); 제거할 요소의 수를 안쓰면 시작 인덱스부터 끝까지 삭제

리턴 값 : 제거한 요소를 담은 배열(제거하지 않았으면 빈배열)

파괴여부 : 파괴

 

삭제를 할때는 두번째 매개변수에 값을 안넣거나 삭제할 개수만큼 값을 넣어주면 된다. 시작인덱스를 포함해서 개수만큼 값을 삭제한다. 이때 배열에 추가할 요소를 넣어주면, 값이 삭제되고 시작인덱스부터 순서대로 값이 들어간다. 그리고 두번째 인덱스에 0을 넣으면 삭제되는 값 없이 해당 인덱스를 포함해서 요소들이 뒤로 밀려나면서 요소들이 추가된다. 그럼 파이썬처럼의 remove 메소드처럼 값을 매개변수로 해서 삭제하는 건 없을까? 없다. 안타깝게도 그런건 없다. 그래서 삭제하려는 값의 인덱스를 찾아서 그 인덱스를 splice 메소드에 넣어서 사용해야한다.

 

❗️indexOf 메소드

이름 : indexOf

메소드 : 배열, 문자열

매개변수 : 찾을 요소, (검색을 시작할 인덱스)

리턴 값 : 배열 내 요소의 최초 인덱스, 발견되지 않으면 -1 (숫자)

파괴여부 : 비파괴

 

indexOf 메소드는 파이썬의 index메소드와 비슷하다. 차이점은 파이썬은 매개변수로 검색을 끝낼 인덱스도 받을 수 있다는 것과 찾고자 하는 값이 없으면 valueError를 일으킨다. JS의 indexOf 메소드는 검색을 시작할 인덱스는 받을 수 있지만, 끝낼 인덱스는 받을 수 없고, 찾고자 하는 값이 없으면 -1을 반환한다. 이걸 조건문에 사용하려면 해당 값이 없을때는 indexOf의 값이 0보다 작다고 써주면 된다. 하지만 splice메소드와 함께 사용할때는 -1이 인덱스로 들어가면 배열의 가장 마지막 요소를 가리킨다는 점을 주의해야 한다.

 

음수 인덱스

파이썬에서는 음수 인덱스를 지원한다. 리스트의 마지막 요소를 -1로 해서 거꾸로 세어가는게 가능하다는 의미이다. 그런데 JS는 음수 인덱스를 지원하지 않는다. 대신 최근에 업데이트 된 메소드가 있다.

 

❗️at 메소드

이름 : at

메소드 : 배열

매개변수 : 인덱스

리턴 값 : 주어진 인덱스에 위치한 배열 요소. 음수값인 경우 배열의 뒤에서부터 인덱스를 센다.

파괴여부 : 비파괴

 

근데 정말 최근에 업데이트가 된 메소드여서 아직 지원이 안되는 경우도 있다. 그런 경우는 객체의 길이에서 원하는 만큼 빼주는 식으로 인덱스 값을 써서 사용하면 된다.

블로그의 정보

Roen의 iOS 개발로그

Steady On

활동하기