JavaScript 배열 및 객체, 반복문

Park, Jinyong·2020년 4월 7일
0

Code States - Pre Course

목록 보기
2/11

Achievement Goals

  • JavaScript의 반복문의 개념을 이해할 수 있다.
  • 배열 및 객체 구조를 이해하고 어떻게 사용하는 지 이해할 수 있다.
  • 다음 용어들에 대해 정확히 이해할 수 있다.
    • dot notation vs. bracket notation
    • index, element, key, value
  • 배열에서 값을 얻어내거나 추가/삭제할 수 있다.

배열

배열은 순서가 있는 값으로 리스트와 비슷한 객체이다. JavaScript에서 배열의 길이와 요소의 자료형은 고정되어 있지 않다. 배열의 요소 인덱스는 무조건 정수만 허용된다. 속성 접근자를 이용하여 배열 리스트의 요소나 배열 객체의 속성과 메서드를 호출할 수 있다.

배열의 생성과 사용

// 배열 생성
let fruits = ['apple', 'banana', 'pineapple']

// 배열 항목에 접근
console.log(fruits[0]); // apple
console.log(fruits[1]); // banana
console.log(fruits[2]); // pineapple

// 배열 요소의 수정
fruits[1] = 'melon'

console.log(fruits); // ['apple', 'melon', 'pineapple']

배열은 [elements, ...] 이렇게 중괄호를 이용해 생성할 수 있다. 항목에 접근하기 위해선 배열 이름에 [index] 를 붙이는 데 index는 0부터 시작하여 1씩 증가한다. 그러므로 마지막 인덱스는 배열의 총 길이 - 1 이다. 배열 인덱스에 접근하면 요소에 값을 대입하여 직접 수정할 수 있다.

배열의 범위를 벗어난 인덱스를 넣으면 undefined를 반환한다.

// 인덱스 범위를 벗어났을 때
console.log(fruits[3]); // undefined

배열의 요소에 배열을 추가하는 다차원 배열을 생성할 수 있다.

// 다차원 배열의 생성
let numbers =[[1, 2], [3, 4], [5, 6]];

// 다차원 배열의 구조
console.table(numbers);

// output:
// ┌─────────┬───┬───┐
// │ (index) │ 0 │ 1 │
// ├─────────┼───┼───┤
// │    0    │ 1 │ 2 │
// │    1    │ 3 │ 4 │
// │    2    │ 5 │ 6 │
// └─────────┴───┴───┘

// 다차원 배열의 접근
console.log(numbers[0]); // [1, 2]
console.log(numbers[0][1]); // 2

다차원 배열 내의 배열에 접근하려면 중괄호를 두 번 써주면 된다.

배열의 속성과 메서드

console.log(fruits); // ['apple', 'melon', 'pineapple']

// 배열의 길이
console.log(fruits.length); // 3
console.log(fruits[fruits.length - 1]); // 'pineapple'

// 배열 마지막에 요소 추가
fruits.push('orange');
console.log(fruits); // ['apple', 'melon', 'pineapple', 'orange']

// 배열의 마지막의 요소 삭제
fruits.pop();
console.log(fruits); // ['apple', 'melon', 'pineapple']

length 속성은 배열의 길이를 가지고 있다. 마지막 요소의 인덱스 + 1 과 동일하다.

push 메서드와 pop 메서드로 마지막 요소를 추가하거나 삭제할 수 있다. push 메서드는 요소 추가 후의 배열 길이를 반환하고, pop 메서드는 꺼내온 마지막 요소를 반환한다.

객체

객체는 데이터와 함수의 집합이다. 보통 데이터는 프로퍼티, 함수는 메서드라고 일컫는다. 객체의 항목은 key와 value 쌍으로 이루어져 있다. key를 통해 value를 호출할 수 있다.

객체의 생성과 사용

// 객체의 생성
let person = {
  name: {firstName: 'Bob', lastName: 'Smith'},
  age: 32,
  gender: 'male',
  interests: ['music', 'skiing', 'game'],
  greeting: function () {
    console.log(`Hi! I'm ${this.name.firstName} ${this.name.lastName}.`);
  }
};

// 객체의 프로퍼티와 메서드에 접근
console.log(person.name.firstName); // Bob
console.log(person.age); // 32
console.log(person.interests[1]); // skiing
person.greeting(); // Hi! I'm Bob Smith.

배열과 달리 항목에 이름이 붙어있기 때문에 항목을 구분하기 쉽다.

Dot notation vs Bracket notation

배열과 달리 객체는 항목에 이름이 붙어있기 때문에 점 표기법(Dot notation)으로 프로퍼티나 메서드를 호출할 수 있다. 만약 괄호 표기법(Bracket notation)으로 접근할 것이라면 항목의 이름을 따옴표로 감싸야 한다.

// 점 표기법
console.log(person.name.firstName); // Bob
console.log(person.age); // 32

// 괄호 표기법
console.log(person['name']['firstName']); // Bob
console.log(person['age']); // 32

둘의 차이점은 점 표기법은 key 이름으로만 value를 호출할 수 있지만, 괄호 표기법은 key 값을 가지고 있는 변수를 이용해 value를 가져올 수 있다는 점이다.

// key 정보를 지닌 변수
let nameSel = 'firstName';

console.log(person.name.nameSel); // undefined
console.log(person.name[nameSel]); // Bob

// key 변경
nameSel = 'lastName';

console.log(person.name.nameSel); // undefined
console.log(person['name'][nameSel]); // Smith

// person.name.nameSel은 person.name.['nameSel']과 같다
// Dot notation과 Bracket notation은 혼용할 수 있다.

person 객체는 nameSel이란 key를 지니고 있지 않기 때문에 undefined가 반환된다. 괄호 표기법에서 따옴표를 없애고 변수를 넣으니 변수가 가진 key 정보에 의해 value가 정상적으로 호출되는 것을 알 수 있다.

in 연산자

객체의 항목에 찾고자 하는 key가 있는지 확인할 수 있다.

console.log('gender' in person); // true
console.log('height' in person); // false

객체 항목 수정, 추가, 삭제

// 객체 항목의 수정
person.age = 25;
person['name']['firstName'] = 'Sam';

// 객체 항목의 추가
person.heigth = 170;
person.weight = 70;

// 객체 항목의 삭제
delete person.interests

console.log(person);


// output:
// {
//   name: { firstName: 'Sam', lastName: 'Smith' },
//   age: 25,
//   gender: 'male',
//   greeting: [Function: greeting],
//   heigth: 170,
//   weight: 70
// }

value에 값을 대입하면 수정된다. 만약 없는 key라면 새로 추가하고 value를 할당한다. delete 연산자는 객체의 항목을 삭제한다.

반복문

for 문

반복문은 한 동작 혹은 여러 동작을 같거나 비슷하게 반복적으로 실행하는 구문이다. 대표적으로 for문이 있다.

for (let i = 0; i < 5; ++i) {
  console.log(i + "번째 출력");
}

// output:
// 0번째 출력
// 1번째 출력
// 2번째 출력
// 3번째 출력
// 4번째 출력

for 문의 구조는 아래와 같이 나눌 수 있다

  • let i = 0; → 초기화 (1)
  • i < 5; → 조건식 (2)
  • console.. → 실행문 (3)
  • ++i → 증감문 (4)

for문의 초기화 부분에서 선언된 변수는 for문 외부에서 접근할 수 없다. 접근하고 싶다면 외부에서 먼저 선언하면 된다.

let i;
for (i = 0; i < 5; ++i) {
  console.log(i + "번째 출력"); // 결과는 위와 같다.
}

console.log(i); // 5

조건식의 조건이 충족되지 않을 때까지 실행문이 계속 반복된다. 한 반복이 끝나면 변수를 증감해서 조건에 점차 가까워진다. ++ii = i + 1과 같다

아래와 같이 중첩 반복문을 만드는 것도 가능하다.

for (let i = 0; i < 2; i++) {
  for (let j = 0; j < 3; j++) {
    console.log('i: ' + i, ', j: ' + j);
  }
}

// output:
// i: 0 , j: 0
// i: 0 , j: 1
// i: 0 , j: 2
// i: 1 , j: 0
// i: 1 , j: 1
// i: 1 , j: 2

for 문을 이용해 무한루프를 만들 수도 있다. 당연히 탈출 조건을 명시해줘야 한다.

for (;;) {
  if (escape condition) {
  	break;
  }
}

for (;escape condition;) {
  statements
}

// 프로그램 종료 전까지 끝나지 않을 무한루프
for (;;);

for 문의 초기화, 조건식, 증감문 모두 선택사항으로 쓰지 않아도 무방하다. break 문은 반복을 멈추고 반복문을 빠져나올 때 사용한다. 만약 중첩 반복문에서 실행되면 해당 반복문만 정지하고 밖의 반복문은 계속 실행된다. 이와 반대로 continue 문도 있다. 반복문 안에서 continue 문을 만나면 현재 하던 반복을 중지하고 다음 반복을 시작한다. 그러니까 continue 아래에 있는, 다음에 실행되어야 할 코드를 무시할 수 있다.

for...in 문, for...of 문

for...in 문과 for...of 문은 배열, 객체, 문자열 등과 같은 반복 가능한 객체의 값을 하나씩 가져와 반복할 수 있게끔 한다.

for...in

for...in 문은 객체의 key를 하나씩 가져온다.

const obj = {
  key1: 'value1',
  key2: 'value2',
  key3: 'value3',
}

for (const key in obj) {
  console.log(obj[key]);
}

// output:
// value1
// value2
// value3

배열과 문자열도 값마다 index, 즉 key를 가지고 있으므로 for...in 문을 사용할 수 있다. 하지만 아래와 같은 문제점이 발생할 수 있다.

const arr = [0, 1, 2];

for (const i in arr) {
  console.log(arr[i + 1]);
}

//output:
// undefined
// undefined
// undefined

const str = 'str';

for (const i in str) {
  console.log(str[i + 1]);
}

//output:
// undefined
// undefined
// undefined

분명 인덱스에 1을 더해서 실행했을 뿐이니 기대되는 출력값은 1, 2, undefinedt, r, undefined일 것이다. 하지만 함정이 있다. 여기서 inumber 타입이 아니라 string 타입이다. 결국, '1'+1연산의 결과는 '11'이 된다. 그래서 모두 undefined가 출력되는 것이다.
이를 방지하기 위해 아래와 같은 트릭을 사용할 수도 있다.

for (const i in arr) {
  console.log(arr[+i + 1]);
}

//output:
// 1
// 2
// undefined

문자열에 + 기호를 붙이면 number타입으로 자동 형변환을 한다. 가독성이 좋지 못하다고 생각된다면, 그냥 일반 for 문을 사용하면 된다.

for...of

for...of 문은 iterable한 속성을 지닌 String, Array, TypedArray, Map, Set에서 값을 하나씩 가져온다. 객체는 iterable이 아니기 때문에 사용할 수 없다. 하지만 Object.keys(object) 혹은 Object.values(object)를 통해 배열로 바꿔서 값을 가져올 수 있다. Object.entries(object)를 이용하면 enumerable 속성의 keyvalue 배열을 동시에 가져올 수 있다.

const obj = {
  key1: 'value1',
  key2: 'value2',
  key3: 'value3',
}

for (const value of obj) { // TypeError: obj is not iterable
  console.log(value);
}

for (const key of Object.keys(obj)) {
  console.log(key);
}
// output:
// key1
// key2
// key3

for (const value of Object.values(obj)) {
  console.log(value);
}
// output:
// value1
// value2
// value3

for (const [key, value] of Object.entries(obj)) {
  console.log(key + ': ' + value);
}
// output:
// key1: value1
// key2: value2
// key3: value3

for...of 문은 iterable하지 못한, 즉 Symbol.iterator key 속성을 지니고 있지 않으면 사용할 수 없다

유사 배열이 그 종류 중 하나이다.

그 외의 반복문

while

조건이 false가 나올 때까지, 혹은 반복문 안에 탈출 조건이 성립할 때까지 반복한다.

while(escape condition) {
  statements
}

무한 루프를 돌릴 때는 무조건 탈출 조건을 명시해야 한다.

while(true) {
  if (escape condition) {
    braek;
  }
}

do...while

while 문과 달리 초기 한 번은 조건 판별 없이 무조건 실행한다.

do {
  statements
} while (escape condition);

0개의 댓글