본문 바로가기

JavaScript

[You don`t Know JS 정리] ch.5 문법

Ch5. 문법

5.1 문과 표현식

  • 문장은 생각을 표현하는 단어들의 완전한 조형물이다. 어구는 구두점이나 접속사로 연결할 수 있고 어구는 더 작ㅇ느 어구로 나눌 수 있다. 어떤 어구는 불완전하여 그 자체로 완성된 문장을 형성할 수 없지만 스스로의 힘만으로 완성되는 어구도 있다.
  • 자바스크립트에서는 문은 문장, 표현식은 어구, 연산자는 구두점/접속사에 해당된다. 자바스크립트에서 모든 표현식은 단일한, 특정한 결괏값으로 계산된다.
var a = 3 * 6
var b = a
b
  • 위 예에서 3*6은 표현식이다. 나머지도 모두 표현식이다.
  • 위 세 줄은 각각 표현식이 포함된 문이다. 세 번째 줄은 표현식의 전부지만 이것만으로도 완전한 문이다. 이런 것을 '표현식 문'이라고 한다.

5.1.1 문의 완료 값

  • 모든 문은 완료 값을 가진다.
  • 콘솔 창은 가장 최근에 실행된 문의 완료 값을 기본적으로 출력하게 되어 있다.
  • 위 예에서 할당 표현식 b = a는 할당 이후의 값이 완료 값이지만, var 문 자체의 오나료 값은 undefined이다.
  • 콘솔 창이 내어준 완료 값은 개발자가 내부 프로그램에서 사용할 수 있는 값은 아니다.
  • 완료 값을 내부 프로그램에서 사용하기 위해서는 ES7 명세에서 사용할 수 있는 do 표현식을 사용하면 된다.
var a, b
a = do {
  if (true) {
    b = 4 + 38
  }
}

a // 42

do {} 표현식은 블록 실행 후 블록 내 마지막 문의 완료 값을 do 표현식 전체의 완료 값으로 반환하며 결국 이 값이 변수 a에 할당된다.

5.1.2 표현식의 부수 효과

  • 부수 효과가 있는 표현식들이 있다.
function foo() {
  a = a + 1
}

var a = 1
foo() // 결괏값은 undefined, 부수 효과는 a에 1이 더해짐
var a = 42
var b = a++

a // 43
b // 42
  • 위 예에서 표현식 a++가 하는 일은 두 가지다. a의 현재값 42를 반환하는 것, 그리고 a를 1만큼 증가시키는 것
  • 단항 연산자인 증가 연산자 / 감소 연산자는 전위 또는 후위 연산자로 사용된다.
var a = 42

a++ // 42
a // 43

++a // 44
a // 44
  • 후위 연산자를 괄호로 감싸도 부수 효과 발생 이후 새 표현식을 만들어 내는 것은 불가능하다.
  • 단 아래 예제처럼 문을 나열하는 콤마 연산자를 사용하면 다수의 개별 표현식을 하나로 연결할 수 있다.
var a = 42,
  b
b = (a++, a)

a // 43
b // 43
  • a++, a 표현식은 두 번째 a 표현식을 첫 번째 a++ 표현식에서 부수 효과가 발생한 이후에 평가한다. 그래서 b 값은 43이다.
  • delete 연산자의 결괏값은 유효한/허용된 연산일 경우 true, 그 외에는 false다. 이 연산자의 부수 효과는 프로퍼티를 제거하는 것이다.
  • = 할당 연산자는 부수 효과와는 무관해 보이지만 a = 42의 실행 결과는 42이고, 본질ㅈ적으로 42를 a에 할당하는 자체가 부수효과이다. 이런 효과는 아래 예처럼 연쇄 할당문에서 특히 유용하다.
  • var a = b = 42처럼 사용하는 것은 잘못된 사용이다. 변수 b를 선언하지 않은 상태에서 실행하면 이 할당문은 b를 직접 선언하지 않는다. 대신 엄격 모드 여부에 따라 에러가 나거나 원치 않은 전역 변수가 생성된다.
var a, b, c
a = b = c = 42

5.1.3 콘텍스트 규칙

  • 자바스크립트 문법 규칙 중에는 같은 구문이지만 어디에서 어떤 식으로 사용하느냐에 따라 서로 다른 의미를 가지는 경우가 있다. 그 중 몇가지만 살펴 본다.
중괄호
  • 자바스크립트에서 중괄호가 나올 법한 곳은 크게 두 군데다.
  1. 객체 리터럴
// bar 함수는 앞에서 정의됨

var a = {
  foo: bar(),
}
  • {}는 a에 할당될 값이므로 객체 리터럴이 맞다.
  1. 레이블
{
  foo: bar()
}
  • 여기서의 { }는 평범한 코드 블록이다. 이 코드 블록은 for/while 루프, if 조건 등에 붙어있는 코드 블록과 기능적으로 매유 유사하다.
  • 여기서 foo는 bar() 문의 레이블이다.
  • 자바스크립트에는 레이블 점프라는 특별한 형태의 goto 장치가 마련되어 있다. continue와 break 문은 선택적으로 어떤 레이블을 받아 goto 처럼 프로그램의 실행 흐름을 '점프'시킨다
foo: for (var i = 0; i < 4; i++) {
  for (var j = 0; j < 4; j++) {
    if (j == i) {
      continue foo
    }
    if ((j * i) % 2 === 1) {
      continue
    }
    console.log(i, j)
  }
}

// 1 0
// 2 0
// 2 1
// 3 0
// 3 2

foo: for (var i = 0; i < 4; i++) {
  for (var j = 0; j < 4; j++) {
    if (i * j >= 3) {
      console.log("그만", i, j)
      break foo
    }

    console.log(i, j)
  }
}

// 0 0
// 0 1
// 0 2
// 0 3
// 1 0
// 1 1
// 1 2
// 그만! 1 3
  • continue foo는 foo라는 레이블이 붙은 루프의 다음 순회를 계속하라는 뜻이다.
  • break foo는 foo라는 레이블이 붙은 바깥쪽 루프/블록 밖으로 나가 그 이후부터 계속하라는 뜻이다.
  • 레이블은 비 루프 블록에 적용할 수 있는데, break만 참조할 수 있다.
function foo() {
  bar: {
    console.log("Hello")
    break bar
    console.log("절대 실행 안 되지!")
  }
  console.log("world")
}

foo()
// Hello
// world
  • 레이블 루프/블록은 사용 빈드고 극히 드물고 못마땅한 구석도 많아 가능한 한 피하는 게 상책이다. 하지만 제한적이나마 도움이 될 때가 있으니 그 때는 주석으로 상세히 기술하도록 하자
JSON은 자바스크립트의 하위 집합이 아니다.
  • JSON 문자열로만 가득 채워진 파일을 "