회고록 블로그

[공부 필기] JavaScript 문법 공부 25일차 (2) 본문

2. 프로그래밍 언어 공부/JavaScript

[공부 필기] JavaScript 문법 공부 25일차 (2)

김간장 2022. 5. 26. 21:42

※ 필자는 초초초보자입니다.

※ 틀린 내용에 대한 피드백은 언제든지 환영합니다.

 

 

공부하고 있는 자료 : modern JavaScript tutorial 

https://ko.javascript.info/array

 

배열

 

ko.javascript.info

 

✅ 배열

- 객체는 기본적으로 순서를 고려하지 않고 만들어진 자료구조이므로

   기존의 프로퍼티 사이에 새로운 프로퍼티를 끼워넣는 등이 불가능하다.

- 이럴 때 사용하는 자료구조가 배열이다.

 

✅ 배열 선언

let arr1 = new Array();
let arr2 = [];

- length를 사용하면 배열에 담긴 요소가 몇 개인지 알아낼 수 있다.

- alert을 사용하면 전체 요소를 출력할 수도 잇다.

- 배열 요소의 자료형엔 제약이 없다.

 

📌 trailing 쉼표

- 객체처럼 마지막 요소는 쉼표로 끝내도 된다.

let arr1 = [
	"apple",
	"orange",
	"pine apple",
];

 

✅ pop과 push , shift와 unshift

- 큐(queue) : 배열을 사용해 만들 수 있는 대표적인 자료구조

   ► 순서가 있는 컬렉션을 저장할 때도 사용한다

 

- 큐에서 사용하는 주요 연산은 다음과 같다.

   ► push : 맨 끝에 요소를 넣어라(?)

   ► shift : 제일 앞 요소를 꺼내고 남아있는 요소들을 앞으로 밀어라(?)

 

- 배열은 큐를 구현하거나, 스택을 구현할 때 자주 사용된다.

   ► 배열에는 요소를 넣고 꺼내는 기능을 해주는 내장 메서드가 있다. push와 pop, shift와 unshift이다.

   ► 배열로 스택을 구현할 때는 push가 요소를 스택 끝에 집어넣고, pop이 스택 요소를 추출한다.

 

※ 스택과 큐를 컴퓨터 과학 분야에선 데큐(deque, Double Ended Queue)라고 한다.

 

 

📌 뒤의 요소를 지지고 볶을 때

- push : 배열의 요소를 끝에 집어넣는다

- pop : 끝 요소를 추출한다. (배열에서는 제거한다)

// pop
let grade = ["1학년", "2학년", "3학년"];

alert(grade.pop()); // 끝의 요소(=3학년) 빼옴
alert(grade); // 끝의 요소(=3학년)는 배열에서 제거된다.
// push
let grade = ["1학년", "2학년", "3학년"];

grade.push("4학년"); //끝에 요소 추가(=4학년 추가)
alert(grade); // 요소 추가돼서 총 4개 요소가 출력됨

 

📌 앞의 요소를 지지고 볶을 때

- unshift : 배열의 앞에 요소를 추가한다.

- shift : 배열의 앞 요소를 추출한다. (해당 요소는 배열에서 제거된다)

let grade = ["1학년", "2학년", "3학년"];

alert(grade.shift()); // 1학년
alert(grade); // 2학년,3학년
let grade = ["1학년", "2학년", "3학년"];

grade.unshift("0학년");
alert(grade); // 0학년,1학년,2학년,3학년

 

✅ 배열의 내부 동작 원리

- 배열은 특별한 종류의 객체이다. 키가 숫자라는 점이 다르다.

- 키가 숫자이기 때문에 배열은 객체 기본 기능 이외에도 순서가 있는 컬렉션을 제어하게 해주는 특별한 메서드를 제공한다.

- 배열도 본질은 객체이기 때문에 length라는 프로퍼티도 제공한다.

 

※ 컬렉션

연관있는 자료들을 모아놓은 자료구조..?

 

- 배열을 배열답게 만들어주는 것은 특수 내부 표현방식이다.

   자바스크립트 엔진은 배열의 요소를 인접한 메모리 공간에 차례로 저장해 연산 속도를 높인다.

   이 외에도 배열 관련 연산을 더 빠르게 해주는 최적화 기법이 다양하게 있다.

   ► 다만 개발자가 배열을 '순서가 있는 자료의 컬렉션'처럼 일반 객체처럼 다루면 최적화 기법 등은 제대로 동작하지 않는다.

 

 

📌 배열을 일반 객체처럼 다루는 경우

- 배열의 길이보다 훨씬 큰 숫자를 사용해서 프로퍼티를 만들 때

   ► 요소를 역순으로 채우거나, grade[99998]과 같이 특정 인덱스에만 값을 채우고 그 사이에는 아무런 요소가 없는 경우

let grade = [];

grade[99998] = 'Hello';

- 임의의 이름을 사용해서 프로퍼티를 만들 때

   ► 숫자가 아닌 값을 프로퍼티 키로 사용하는 경우

let grade = [];

grade.age = 10;

- 배열은 객체이므로 위와 같이 프로퍼티를 추가해도 문제가 발생하지 않는다.

- 하지만, 이렇게 작성하면 자바스크립트 엔진이 배열을 일반 객체처럼 다루기 때문에

   배열을 다룰 때만 적용되는 최적화 기법이 동작하지 않아서

   배열 특유의 이점이 사라진다.

 

✅ 성능

- push / pop은 빠르지만 shift / unshift는 느리다.

 

- 간단하게 생각해봐도, 배열 앞에 값을 빼내고 나머지 요소들을 한 칸씩 앞으로 이동시키는 것은

   배열에 요소가 많아질수록 요소가 이동하는데 걸리는 시간이 길고 메모리 관련 연산도 많아지기 때문에 느릴 수 있다.

 

- 하지만 반대로 배열의 뒤에서 값을 빼내면, 나머지 요소들의 인덱스를 그대로 유지해둘 수 있으므로

   실행 속도가 더 빠르다.

 

✅ 반복문

- 배열을 순회할 때 사용하는 반복문은 다음과 같다.

   ► for

   ► for...of : 현재 요소의 인덱스는 얻을 수 없고 값만 얻을 수 있다.

   ► for...in : 배열도 객체형에 속하므로 for...in문을 사용할 수 있다.

let grade = ["1학년", "2학년", "3학년", "4학년", "5학년", "6학년"];

for (let number of grade) {
	console.log(number);
}

for (let key in grade) {
	console.log(grade[key]);
}

 

- 다만 for...in문은 다음과 같은 특징을 지니기 때문에 배열에 사용하는 것을 추천하지 않는다. (문제가 발생할 수 있다)

   ► 모던 자바스크립트 내용 발췌 (출처 : https://ko.javascript.info/array)

1. for..in 반복문은 모든 프로퍼티를 대상으로 순회합니다.
키가 숫자가 아닌 프로퍼티도 순회 대상에 포함됩니다.
브라우저나 기타 호스트 환경에서 쓰이는 객체 중, 배열과 유사한 형태를 보이는 ‘유사 배열(array-like)’ 객체가 있습니다.
유사 배열 객체엔 배열처럼 length 프로퍼티도 있고 요소마다 인덱스도 붙어 있죠.
그런데 여기에 더하여 유사 배열 객체엔 배열과는 달리 키가 숫자형이 아닌 프로퍼티와 메서드가 있을 수 있습니다.
유사 배열 객체와 for..in을 함께 사용하면 이 모든 것을 대상으로 순회가 이뤄집니다.
따라서 ‘필요 없는’ 프로퍼티들이 문제를 일으킬 가능성이 생깁니다.

2. for..in 반복문은 배열이 아니라 객체와 함께 사용할 때 최적화되어 있어서 배열에 사용하면 객체에 사용하는 것 대비 10~100배 정도 느립니다.
for..in 반복문의 속도가 대체로 빠른 편이기 때문에 병목 지점에서만 문제가 되긴 합니다만,
for..in 반복문을 사용할 땐 이런 차이를 알고 적절한 곳에 사용하시길 바랍니다.

 

✅ length 프로퍼티

- 배열에 무언가 조작을 가하면 length 프로퍼티가 자동으로 갱신된다.

- length 프로퍼티는 배열 내 요소의 개수가 아니라 가장 큰 인덱스에 1을 더한 값이다.

let grade = ["1학년", "2학년", "3학년", "4학년", "5학년", "6학년"];
console.log(grade.length); // 6

grade[200] = 'None';
console.log(grade.length); // 201

 

- length의 독특한 특징 중 또 하나는 [쓰기가 가능하다]는 점이다.

   ► 값을 수동으로 증가시키면 아무 일도 일어나지 않지만

   ► 값을 감소시키면 배열이 잘린다.

   ► 잘린 배열은 다시 되돌릴 수 없다.

let grade = ["1학년", "2학년", "3학년", "4학년", "5학년", "6학년"];

// length 증가시키기
grade.length++;
console.log(grade.length); // 7

// length 줄이기
grade.length = 3;
console.log(grade.length); // 3
alert(grade); //1학년,2학년,3학년

// length 다시 복구해보기
grade.length = 6;
alert(grade); //1학년,2학년,3학년,,,

 

✅ new Array()

- new Array() 를 통해서 배열을 만들 수도 있다.

- 잘 사용되지는 않는다고 한다.

   ► new Array()에 까다로운 기능이 있기 때문에..

 

- 숫자형 인수를 하나 넣어서 new Array를 호출하면 배열이 만들어진다.

   다만 까다로운 점은... 배열엔 요소가 없는데 길이는 인수와 같아진다.

   ► new Array(3)으로 배열을 만들면 length는 3이 된다.

let grade = new Array(3);
console.log(grade.length); // 3

   ► 다만 배열의 요소들을 출력해보면 모두 undefined이다. (요소가 하나도 없다)

for (let value of grade) {
	console.log(value); //undefined
}

 

- 이런 뜻밖의 상황을 마주치지 않기 위해서 new Array의 기능을 잘 사용하지 않는다고 한다.

 

✅ 다차원 배열

- 2차원, 3차원 배열로 선언할 수 있다.

   /* 메모리에는 1차원으로 저장되겠지만... */

- 다차원 배열은 행렬을 저장하는 용도로 쓰인다.

let grade = [
	[1, 2, 3],
	[4, 5, 6],
	[7, 8, 9]
];

alert(grade); //1,2,3,4,5,6,7,8,9

alert(grade[0][0]); // 1
alert(grade[1][0]); // 4

 

✅ toString 메서드

- 배열에도 있다. toString 메서드

   /* 저번에 숫자형 공부할 때 toString 메서드를 배웠고 객체의 형 변환할 때도 toString을 호출한다고 배웠었다 */

- 이를 호출하면 쉼표로 구분한 문자열이 반환된다.

   ► alert으로 출력한 결과처럼

 

- 배열에는 Symbol.toPrimitive나 valueOf 메서드가 없다.

   따라서 배열이 문자열로 형 변환이 일어날 때는 다음과 같이 변환된다.

   [] → 빈 문자열

   [1] → 문자열 "1"

   [1,2] → 문자열 "1,2"

Comments