자바스크립트 완벽 가이드 7판 스터디
책의 목차를 따라가며 관련 내용을 학습하고 공유하는 스터디입니다.

1. 문(statement)이란?
2. 조건문 - if/else, switch
3. 반복문 - for
4. for/of
5. for/in
6. 점프 - break, continue, 라벨

예외처리(try/catch/finally/throw) 관련해서는 따로 정리를 해야할 것 같다..!


1. 문(statement)이란?

  • 문장이나 명령어라고 할 수 있다.
  • 문(statement)는 세미콜론으로 끝난다(구분한다).
    • ; 세미콜론 하나만 있으면 빈 문(statement)이다.
  • 표현식은 '평가'를 통해 값으로 바뀌지만, 문은 '실행'을 통해 어떤 동작을 수행한다.
  • 할당이나 함수 호출처럼 사이드 이펙트가 있는 표현식은 그 자체로 문이 될 수 있다.
  • 자바스크립트 인터프리터는 문들을 작성된 순서대로 실행한다.
  • 표현문, 선언문, 제어문 등이 있다.

2. 조건문 - if/else, switch

if/else

  • if, else 키워드 뒤에는 문 하나만 올 수 있다.
    • else if 라는 건 없다. else 뒤에 하나의 문이 올 수 있는데 그 하나의 문이 if문인 것이다.
  • 뒤에 오는 문을 {}로 감싸는 경우가 많다.
    • 중괄호를 쓰는 것이 훨씬 가독성이 뛰어난 것 같다.
// if
if (expression) statement;

// if else
if (expression) statement1;
else statement2;

switch

  • switch(expression)expression과 case 표현식을 ===로 비교해서 일치하면 해당 case의 코드 문을 실행한다.
  • 일치하는 case를 찾으면 그 시점부터 하단의 내용이 전부 출력된다.
  • default로 일치하는 case가 없을 경우를 분기시킨다. eslint에서는 default를 꼭 사용하도록 강제한다.
  • 오류를 줄이기 위해 case 문을 블록으로 감싸는 것도 때때로 필요하다.
const browser = 'Whale';

switch (browser) {
  // case 문을 {}로 감싸기
  case 'IE': {
    console.log('go away!');
    break; // 종료, break가 case일치 시점부터 하단의 내용이 전부 출력
  }

  case 'Chrome': // or 의 경우 붙여 씀
  case 'Whale':
    console.log('come here!');
    break;

  default:
    //일치하는 case가 없는 경우
    console.log('what!?');
}
// print: come here!

맵핑으로 if문 제거하기

  • 코드양은 비슷하다. 어떻게 분리하는지가 중요하다.
  • 맵핑을 사용하면 내부 로직을 숨기고 전체 로직만 가독성있게 확인할 수 있다.
const moveUp = () => console.log('위로 이동');
const moveDown = () => console.log('아래로 이동');
const moveLeft = () => console.log('왼쪽으로 이동');
const moveRight = () => console.log('오른쪽으로 이동');
const saveLog = moveType => console.log('SaveLog: ' + moveType);

function move(moveType) {
  if (moveType === 'up') {
    moveUp();
    saveLog('위');
  } else if (moveType === 'down') {
    moveDown();
    saveLog('아래');
  } else if (moveType === 'left') {
    moveLeft();
    saveLog('왼쪽');
  } else if (moveType === 'right') {
    moveRight();
    saveLog('오른쪽');
  }
}
const moveUp = () => console.log('위로 이동');
const moveDown = () => console.log('아래로 이동');
const moveLeft = () => console.log('왼쪽으로 이동');
const moveRight = () => console.log('오른쪽으로 이동');
const saveLog = moveType => console.log('SaveLog: ' + moveType);

const moveMap = {
  up() {
    moveUp();
    saveLog('위');
  },
  down() {
    moveDown();
    saveLog('아래');
  },
  left() {
    moveLeft();
    saveLog('왼쪽');
  },
  right() {
    moveRight();
    saveLog('오른쪽');
  },
};

function move(moveType) {
  moveMap[moveType]();
}

3. 반복문 - for

for (initialize; test; increment) {
  statement;
}
  • initiallize : 변수 선언문 또는 할당문. 루프를 시작하기 전 한 번 평가
  • test : 조건식. 이 조건을 평가해 참인 경우 statement를 실행
  • statement : 조건식이 참인 경우 반복 실행될 문
  • increment : statement의 끝에서 변수를 다시 테스트하기 직전에 업데이트
  • initialize, test, increment 세 가지 전부 생략가능하다. 단 세미콜론은 필수
    • 세 가지 전부 생략한 경우 => for (;;)

4. for/of

  • ES6에서 추가.
  • 이터러블 객체에서만 동작한다.
    • 이터러블은 Symbol.iterator 메서드를 갖고 있다. 이 메서드가 있어야 for/of를 사용할 수 있다.
    • ES6에서 유사 배열 객체인 arguments, NodeList, HTMLCollection 객체에 Symbol.iterator 메서드를 구현하여 이터러블이 되었다.
  • 일반 객체를 순회하고자 할 땐 Object.entries, Object.values, Object.keys 를 사용한다.

for/of 사용 방법

for (variable declaration of iterable) {
  statement
}
  • iterable을 순회하면서 iterable 요소를 변수에 할당한다.
  • 내부적으로는 이터레이터의 next 메서드를 호출하여 next 메서드가 반환한 result 객체의 value 프로터피 값을 변수에 할당한다.
  • result 객체의 done 프로퍼티 값true면 순회를 중단한다.

for/of 의 내부동작을 for 문으로 구현

const iterable = [1, 2, 3];
for (const item of iterable) console.log(item);
// 1
// 2
// 3
const iterable = [1, 2, 3]; // 배열은 이터러블이다.

const iterator = iterable[Symbol.iterator](); // 이터레이터 생성

for (;;) {
  const result = iterator.next(); // next 메서드를 호출해 이터러블을 순회
  console.log(result); // next 메서드가 반환한 result 객체
  if (result.done) break; // done 프로퍼티 값이 true면 순회 중단
  const item = result.value; // value 프로퍼티 값이 item 변수에 할당
  console.log(item);
}

// { value: 1, done: false }
// 1
// { value: 2, done: false }
// 2
// { value: 3, done: false }
// 3
// { value: undefined, done: true }

// 위의 코드와 똑같은 코드

5. for/in

  • 자바스크립트 초창기부터 존재했다.
  • 객체의 프로퍼티를 순회하며 열거한다.
    • 순회하는 객체의 프로퍼티뿐만 아니라 상속받은 프로토타입의 프로퍼티까지 열거한다.
    • 단, 프로퍼티의 속성 [[Enumerable]]의 값이 true인 것만 열거할 수 있다.
      • [[Enumerable]]은 프로퍼티의 열거 가능 여부를 나타내며 불리언 값이다.
    • 프로퍼티의 키가 Symbol인 프로퍼티는 열거하지 않는다.
    • 열거할 때 순서를 보장하지 않는다.

따라서 for/in문은 객체의 프로토타입 체인에 있는 모든 프로토타입의 프로터피 중, 프로퍼티의 속성 [[Enumerable]]의 값이 true인 것만 열거한다.


for/in 사용 방법

for (variable declaration of object) {
  statement
}
  • 변수에 object 객체의 프로퍼티 키가 할당된다.

const dog = {
  name: 'Enum',
  age: '5',
  __proto__: { gender: 'male' },
  walwal: function () {
    console.log('왈왈');
  },
  [Symbol()]: 10, // 키가 심볼인 프로퍼티는 열거 x
};

for (const key in dog) {
  console.log(`${key}: ${dog[key]}`);
}

// name: Enum
// age: 5
// walwal: () => console.log('왈왈') // 열거 순서를 보장하지 않는다.
// gender: male // 상속된 프로퍼티도 열거한다.

for/in은 다른 걸로 대체하자

  • 성능이 낮다.
  • 객체 자신의 고유 프로퍼티만 열거하려면 => Object.entries, Object.values, Object.keys
  • 배열은 forEach

6. 점프 - break, continue, 라벨

  • 자바스크립트 인터프리터가 소스 코드의 다른 위치로 이동하게 한다.
  • break : 루프를 비롯한 다른 문의 끝으로 이동
  • continue : 루프 바디의 나머지를 생략하고 루프 맨 위로 돌아가 새 반복을 시작

// 예시

function solution(s) {
  let count = 0;

  for (let x = 0; x < s.length; x++) {
    let state = true;
    const stack = [];
    const replaced = [...s.substring(x), ...s.substring(0, x)];

    for (const bracket of replaced) {
      if (isOpen(bracket)) {
        stack.push(bracket);
        continue; // 아래 생략하고 다시 맨 위로 돌아감
      }

      if (isMatched(stack[stack.length - 1], bracket)) {
        stack.pop();
        continue; // 아래 생략하고 다시 맨 위로 돌아감
      }

      state = false;
      break; // 루프 문의 끝으로 이동, 밑에 if문으로 이동함
    }
    if (state === true && stack.length === 0) count++;
  }

  return count;
}

  • 문 앞에 라벨을 붙여 break, continue를 사용할 때 문을 특정할 수 있다.
  • identifier: statement
// 예시 1

loop1: for (let i = 1; i <= 3; i++) {
  loop2: for (let j = 10; j <= 13; j++) {
    if (j === 12) break loop2; // loop2를 탈출하지만 loop1은 계속 진행
    console.log(i, j);
  }
}

// 1 10
// 1 11
// 2 10
// 2 11
// 3 10
// 3 11
// 예시 2

loop1: for (let i = 1; i <= 3; i++) {
  loop2: for (let j = 10; j <= 13; j++) {
    if (j === 12) break loop1; // loop1을 즉시 탈출
    console.log(i, j);
  }
}

// 1 10
// 1 11


참고자료

0개의 댓글