문과 표현식
자바스크립트에서 문과 표현식은 중요한 차이가 있다.
var a = 3 * 6;
var b = a;
b;
3 * 6은 표현식이다.
두번째 줄과 세번째 줄 또한 표현식이다.
var a = 3 * 6, var b = a 두 문은 각각 변수를 선언 하므로 선언문 이라 한다.
a = 3 * 6 이나 b = a는 할당 표현식 이라 한다.
세번째 줄은 표현식의 전부이지만 이것만으로 완벽한 문이다.
일반적으로 이 문은 표현식 문이라 한다.
1 - 문의 완료 값
모든 문은 완료 값을 갖는다. 심지어 undefined값을 갖을 수 있어도 갖는다.
var문의 완료값은 undefined이다.
실제로 var a = 42를 콘솔창에 실행시켜 보면 42 대신 undefined가 나온다.
이는 콘솔이 실행한 문의 완료 값을 보고한 것이다.
{ } 블록은 내부의 가장 마지막 문/표현식의 완료 값을 자신의 완료값으로 반환한다.
var b;
if(true) {
b = 4 + 38; // 42
}
콘솔 창에서 실행하면 42가 나온다.
블록 내의 마지막 문 b = 4 + 38의 완료 값이 42이므로 if블록의 완료 값도 42를 반환한다.
즉, 블록의 환료 값은 내부에 있는 마지막 문의 값을 암시적으로 반환한 값이다.
do { } 표현식은 블록 실행 후 블록 내 마지막 문의 완료 값을 do
표현식 전체의
완료 값으로
반환하며 결국 이 값이 변수 a에 할당된다.
var a, b;
a = do {
if(true) {
b = 4 + 38;
}
};
a; // 42
인라인 함수 표현식 안에 감싸서 명시적으로 반환할 필요 없이 문을 표현식처럼 다루자는 게 기본적인 아이디어이다.
2 - 표현식의 부수 효과
대부분의 표현식에는 부수 효과가 없다.
var a = 2;
var b = a + 3;
표현식 a + 3 자체는 a 값을 바꾸는 등의 부수효과가 전혀 없다.
단지, b = a + 3 문에서 결과값 5가 b에 할당될 뿐이다.
부수효과가 있는 경우를 보자
- ++ / -- 를 이용한 전위 연산자, 후위 연산자
- 문을 나열하는 콤마 연산자( , )를 사용해 다수의 개별 표현식을 하나의 문으로 연결
var a = 42, b;
b = (a++, a);
a; // 43
b; // 43
- 객체의 프로퍼티나 배열에서 슬릇을 없애는 delete 연산자
delete 연산자의 결과값은 유효한 허용된 연산일 경우 true, 그 외에는 false이다.
var obj = {
a: 42
};
obj.a; // 42
delete.obj.a; // true
obj.a; // undefined
- = 할당 연산자
이미 선언된 변수에 값을 할당하는 것이 본질적으로 부수 효과이다.
var a;
a = 42; // 42
a; // 42
3 - 콘텍스트 규칙
중괄호
중괄호가 들어가는 곳은 크게 두 군데이다.
1) 객체 리터럴
// bar() 함수는 앞에 정의됨
var a = {
foo: bar()
};
2) 레이블
{
foo: bar()
};
{ } 는 어디에도 할당되지 않은, 그저 고립된 객체 리터럴 처럼보이지만, 전혀 그렇지 않다.
이 { } 블록은 for/while 루프, if 조건 등에 붙어있는 코드 블록과 기능적으로 매우 유사하다.
foo: bar() 구문이 특이하게 보이는 이유는 Javascript에서 레이블 문이라 부르는 기능 덕분이다(비추천....)
continue와 break문은 선택적으로 어떤 레이블을 받아 goto처럼 프로그램의 실행 흐름을 점프시킨다.(goto문은 코드를 난해하게 만드는 스파게티 코드의 주범이므로 사용은 비추)
break foo는 foo라는 레이블 위치로 이동하여 계속 순회하라는 의미가 아니다.foo 레이블이 붙은 바깥쪽 루프/블록 밖으로 나가 그 이후부터 계속하라는 의미이다.
JSON이 자바스크립트에서는 에러가 난다.
그래서 JSON-P(JSON데이터를 foo({"a":42})와 같은 함수 호출로 감싸는 패턴) 방식으로
자바스크립트 함수 중 하나에 이 값을 인자로 실어 보내면 접근이 안되는 문제를 해결할 수 있다.
하지만, 사실은 그렇지 않다.....
{"a": 42}는 완전히 올바른 JSON 값이지만, 그 자체로는 레이블이 잘못된 문 블록으로 해석되어 에러가 난다.
JSON-P가 JSON을 문법에 맞는 자바스크립트 코드로 옷을 갈아입혀 주는 꼴이다.....
3) 블록
[] + {}; // "[object Object]"
{} + []; // 0
윗줄에서 엔진은 + 연산자 표현식의 {}를 실제 값(빈 객체)으로 해석했다.
[]는 " " 로 강제변화 되고 {}도 문자열 "[object Object]"로 강제변환됨.
아랫줄의 {}는 동떨어진(아무 일도 하지 않는) 빈 블록으로 간주.
결국 + [] 표현식에서 명시적으로 []를 숫자 0으로 강제변환
4) 객체 분해
ES6부터 분해 할당, 객체 분해 시 { }를 사용한다.
function foo ({a, b, c}) {
console.log(a, b, c);
}
foo({
c: [1, 2, 3],
a: 42,
b: "foo"
}); // 42, "foo", [1, 2, 3]
위와같이 객체 분해는 명명된 함수에도 활용할 수 있다.
5) else if와 선택적 블록
사실 else if라는 문은 없다...
자바스크립트 문법의 숨겨진 특성이지....
여러 스타일 가이드 문서에는 다음 처럼 단일 문 블록도 { }로 감싸라고 조언한다.
즉, else if 라고 쓴느 것은 표준 스타일 가이드의 위반 사례가 되며,
단일 if 문과 같이 else를 정의한 셈이다.
물론 else if는 이미 다 쓰는 관용 코드이고, 한 단계 하위로 들여 쓰기를 하는 효과가 있어 매력은 있다.
'JavaScript > You Don't know JS' 카테고리의 다른 글
I don't know JS YET) 문법 - 세미콜론 자동 삽입 (0) | 2022.07.09 |
---|---|
I don't know JS YET) 문법 - 연산자 우선순위 (0) | 2022.07.06 |
I don't know JS YET 강제변환 (0) | 2022.04.28 |
I don't know JS YET 네이티브 (0) | 2022.04.08 |
I don't know JS YET 특수값(값이 아닌 값, undefined, 특수 숫자, 특이한 동등비교, 값과 레퍼런스) (0) | 2022.03.29 |