자바스크립트가 동작하게 코드를 작성하는 것은 어렵지 않습니다. 그러나 정확한 문법을 알고, 온갖 자바스크립트적 허용이 주는 혼란에 빠지지 않고 코드를 작성할 수 있는 것은 별개의 문제입니다. 이번 글에서는 이러한 불분명한 코드들을 걷어내기 위해 JS의 문법에 대해 알아봅니다.
- 문과 표현식
흔히 어떤 JS 코드를 지칭할때 문(statement)과 표현식(expression)을 혼용해서 많이 사용합니다. 그러나 둘의 단어가 다르듯 서로 가리키는 대상도, 범위도 분명히 다른 용어입니다. 그렇다면 어떻게 다른지 예시를 통해 살펴보겠습니다.
var test = 123 + 456;
위 코드에서 문과 표현식은 어떻게 찾을 수 있을까요?
자바스크립트에서 문은 완성된 하나의 코드 뭉치를 의미합니다. 영어 문법에서도 주어와 동사가 합쳐져야 비로소 기본적인 문장이 완성되듯, 코드에서도 문은 그 자체로 완성된 모습이어야 합니다.
표현식은 특정한 결과값으로 계산되는 코드를 의미합니다. 영어 문장에서의 어구(phrase)로도 표현됩니다. 그렇다면 위 코드를 표현식과 문으로 나누어보면 아래와 같습니다.
문 : var test = 123 + 456;
표현식 : 123 + 456
특정한 결과값을 갖는 우변의 123 + 456은 표현식의 조건을 만족하고 있습니다. 또한 test라는 변수를 선언하여 표현식 123 + 456의 값을 할당하는 라인 자체는 완성된 하나의 구문이므로, 문이라고 볼 수 있습니다.
예시를 통해 문과 표현식의 조건을 알 수 있었습니다. 눈치채셨겠지만, 문과 표현식을 구분하는 가장 결정적인 요소는 바로 결과값입니다.
크롬의 개발자 도구 (Ctrl + Shift + I) 를 열어 콘솔에 위 코드들을 입력해서 확인해보겠습니다.
콘솔에 위 표현식과 문을 입력하게 되면, 기본적으로 각각의 결과값을 리턴합니다. 여기서 표현식은 579라는 특정한 결과값을 갖는 것을, 문은 undefined라는 결과값을 반환하는 것을 확인할 수 있습니다.
어째서 test라는 변수에 579라는 값을 할당하는 문의 결과값이 579가 아니라 undefined 인건지, 뭔가 이상하다고 느끼셨을지도 모르겠습니다. 코드를 입력중에 실수를 하셨다거나 하는건 아니고, 변수 선언문의 결과값이 undefined로 고정되어 있기 때문에 정상적인 결과입니다. 비단 var뿐 아니라 let과 const도 똑같습니다.
정확히는 변수 선언의 결과값으로는 문자열이 반환되도록 되어있지만, 이 결과값을 다른 알고리즘에서 받고 undefined를 반환하도록 짜여져 있기 때문에 이상한 것이 아닙니다. 자세한 내용은 다음에 따로 다루도록 하겠습니다.
- 콘텍스트 규칙
중괄호 { }
중괄호는 스코프 개념과 함께 자세히 설명할 예정이니 여기서는 짧게 다루겠습니다. 중괄호에는 여러가지 쓰임이 있는데 그 중 하나가 객체 리터럴입니다. 어떠한 변수에 할당될 값들을 감싸주는 역할을 합니다.
1
2
3
|
let item = {
pencil: 1;
};
|
cs |
중괄호로 감싸진 리터럴을 변수 item에 할당시켜주는 코드입니다.
또 다른 쓰임으로는 레이블이 있습니다.
1
2
3
|
{
item: pencil()
}
|
cs |
위 코드처럼 사용된 중괄호는 레이블을 의미합니다. 하나의 평범한 코드 블록인데, let과 함께 사용하면 굉장히 유용해집니다.
라벨(label) 이라고도 부르는 이 레이블은 일상생활에서는 상품 따위에 붙어있는 상표 스티커를 의미합니다. 문구점에서도 라벨지라는 이름의 사무용품을 쉽게 찾아볼 수 있습니다. 라벨지는 보통 문서나 상품에 붙여 대상을 분류하는 역할을 하는데, 자바스크립트에서도 비슷한 의미로 생각할 수 있습니다. 레이블 문은 코드상에서의 특정한 부분을 따로 이름붙여 구분합니다. 코드에서도 일상에서처럼 특정한 대상을 구분하는 역할에 초점을 맞추시면 이해하기 편합니다.
다른 언어를 먼저 접하셨던 분이라면 goto문에 대해 알고있던 분들이 계실텐데, goto문을 활용하기 위한 자바스크립트의 문법이라고 생각하셔도 좋습니다.
코드를 통해 예시를 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
|
firstlabel: for(let i = 0; i<10; i++) {
for(let j = 0; j<5; j++) {
if(something) {
break firstlabel;
}
}
}
|
cs |
레이블 문을 이렇게 사용하면 2중 for문의 안쪽에서 break를 통해 바깥쪽의 루프문까지 한 번에 탈출할 수 있게 됩니다. 얼핏 유용하다고 느껴질 수 있으나, goto문이 늘 그렇듯... 사용은 최대한 지양하는게 깔끔한 코드를 위해 좋다는 생각이 드네요.
객체 분해
중괄호는 객체 분해에도 적용됩니다. ES6의 대표적인 문법이라고 할 수 있는 구조 분해 할당에서도 찾아볼 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
|
function menuList() {
return {
americano: 1500,
caffelatte: 3000
}
}
...
var { americano, caffelatte } = menuList();
console.log(americano, caffelatte); // 1500, 3000
|
cs |
선언만으로도 객체가 갖고있는 변수를 간단히 할당할 수 있어 자주 사용되는 용법입니다. 기억해두시면 유용하게 사용하실 수 있을 것 같네요.
- 연산자 우선순위
연산자는 고유한 우선순위 규칙에 의해 순서대로 연산됩니다. 우선순위 규칙은 연산자가 한 두개 있을때보다는 여러개 중첩되어 있을때 더 빛을 발합니다.
우리는 강제변환 파트에서 논리 연산자들이 boolean 값이 아닌 피연산자 중 하나를 반환하는 것을 확인했었습니다. 이러한 자바스크립트의 특성이 더해져 어떤 규칙을 갖고 연산이 되는지 확실히 알아두지 않으면 복잡한 연산자들로 이루어진 표현식을 보고 혼동할 수 있으니, 모든 연산자의 우선순위를 외우지는 못하더라도 자주 사용되는 연산자들끼리는 어느정도 알아두는 것이 편리합니다.
또한 연산자들은 종류에 따라 서로 다른 결합성을 갖습니다. 결합성이란 연산의 진행 방향과 같다고 볼 수 있는데, 좌결합성은 왼쪽에서 오른쪽으로 결합하고, 우결합성은 오른쪽에서 왼쪽으로 결합하는 형태입니다.
서로 다른 연산자끼리 함께 있을때는 결합성은 큰 의미가 없지만, 같은 연산자 우선순위를 갖는 연산자가 붙어 있는 경우엔 결합성이 중요해집니다. 연산 순서에 따라 결과값이 달라지기 때문입니다.
결합성의 경우 우리가 이미 알고있던 상식선에서 크게 벗어나지는 않으니 너무 걱정하지 않으셔도 됩니다. 아래는 MDN에서 안내하는 연산자의 우선순위와 결합성을 정리한 표입니다.
우선순위연산자 | 유형 | 결합성 | 연산자 |
21 | 그룹 | 없음 | ( … ) |
20 | 멤버 접근 | 좌결합성 | … . … |
계산된 멤버 접근 | 좌결합성 | … [ … ] | |
new (매개변수 리스트 존재) | 없음 | new … ( … ) | |
좌결합성 | … ( … ) | ||
Optional chaining | 좌결합성 | ?. | |
19 | new (매개변수 리스트 생략) | 우결합성 | new … |
18 | 후위 증가 | 없음 | … ++ |
후위 감소 | … -- | ||
17 | 논리 NOT (en-US) | 우결합성 | ! … |
비트 NOT | ~ … | ||
단항 양부호 | + … | ||
단항 부정 | - … | ||
전위 증가 | ++ … | ||
전위 감소 | -- … | ||
typeof | typeof … | ||
void | void … | ||
delete | delete … | ||
await | await … | ||
16 | 거듭제곱 | 우결합성 | … ** … |
15 | 곱셈 | 좌결합성 | … * … |
나눗셈 | … / … | ||
나머지 | … % … | ||
14 | 덧셈 | 좌결합성 | … + … |
뺄셈 | … - … | ||
13 | 비트 왼쪽 시프트 | 좌결합성 | … << … |
비트 오른쪽 시프트 | … >> … | ||
비트 부호 없는 오른쪽 시프트 | … >>> … | ||
12 | 미만 | 좌결합성 | … < … |
이하 | … <= … | ||
초과 | … > … | ||
이상 | … >= … | ||
in | … in … | ||
instanceof | … instanceof … | ||
11 | 동등 | 좌결합성 | … == … |
부등 | … != … | ||
일치 | … === … | ||
불일치 | … !== … | ||
10 | 비트 AND | 좌결합성 | … & … |
9 | 비트 XOR | 좌결합성 | … ^ … |
8 | 비트 OR | 좌결합성 | … | … |
7 | 널 병합 연산자 | 좌결합성 | … ?? … |
6 | 논리 AND (en-US) | 좌결합성 | … && … |
5 | 논리 OR (en-US) | 좌결합성 | … || … |
4 | 조건 | 우결합성 | … ? … : … |
3 | 할당 | 우결합성 | … = … |
… += … | |||
… -= … | |||
… **= … | |||
… *= … | |||
… /= … | |||
… %= … | |||
… <<= … | |||
… >>= … | |||
… >>>= … | |||
… &= … | |||
… ^= … | |||
… |= … | |||
2 | yield | 우결합성 | yield … |
yield* | yield* … | ||
1 | 쉼표 / 시퀀스 | 좌결합성 | … , … |
자세한 내용은 MDN 문서를 참조해주세요.
정리
오늘은 자바스크립트 코드의 기본이 되는 단위인 문과 표현식에 대해 알아보았습니다. 콘텍스트 규칙, 그 중에서도 중괄호에 대한 내용을 공부하였고, 구조 분해 할당을 적용하기 위한 객체 분해에 대해서도 알아보았습니다.
연산자의 우선순위와 결합성의 개념에 대해서도 새로 배웠습니다. 당장 모든 연산자들의 우선순위를 외우지는 않더라도, 자주 사용되는 연산자에 대해서는 어느정도 기억해두고 넘어가시는게 좋겠습니다.
다음은 스코프에 대한 내용입니다. 쉽지만은 않은 내용이니 천천히 다루어보겠습니다.
'이론 > Frontend' 카테고리의 다른 글
JavaScript의 스코프 - 1 (Scope of JavaScript) (0) | 2021.04.11 |
---|---|
Jest 기본 사용법 (0) | 2021.04.03 |
JavaScript의 강제변환 - 3 (Coercive Type Conversion of JavaScript) (0) | 2021.03.09 |
JavaScript의 강제변환 - 2 (Coercive Type Conversion of JavaScript) (0) | 2021.03.05 |
JavaScript의 강제변환 - 1 (Coercive Type Conversion of JavaScript) (0) | 2021.03.02 |
댓글