표현식의 부수 효과
대부분의 표현식에는 부수 효과가 없다. 예컨데,
var a = 2;
var b = a + 3;
표현식 a + 3
자체는 가령 a값을 바꾸는 등의 부수효과가 전혀 없다. 단지 b = a + 3
문제서 결괏값 5가 b에 할당될 뿐이다.
다음의 함수 호출 표현식은 부수효과를 가진 표현식의 전형적인 예다.
function foo() {
a = a + 1;
}
var a = 1;
foo(); // 결괏값 : undefined, 부수 효과 : a가 변경됨
다른 부수 효과를 지닌 표현식을 보자.
var a = 42;
var b = a++;
표현식 a++
이 하는 일은 두 가지다. a의 현재 값 42를 반환하고 a값을 1만큼 증가시킨다.
var a = 42;
var b = a++;
a; // 43
b; // 42
여기서 b값을 43으로 착각하는 개발자들이 생각보다 많다. 무엇보다 ++연산자에 부수효과가 있다는 걸 잘 모르니까 더 헷갈리는 것이다.
단항 연산자인 증가 연산자/감소 연산자는 전위 또는 후위 연산자로 사용한다.
var a = 42;
a++; // 42
a; // 43
++a; // 44
a; // 44
++를 전위 연산자로 사용하면 표현식으로부터 값이 반환되기 전에 부수 효과를 일으킨다. 반면, 후위 연산자로 사용하면 값을 반환한 이후에 부수 효과가 발생한다.
++a++은 문법에 맞는 구문일까? 실행하면 ReferenceError 에러가 난다. 부수 효과를 유발하는 연산자는 부수효과를 일으킬 변수 레퍼런스가 꼭 필요하기 때문이다. ++a++에서는 a++부분이 먼저 평가되어 증가되기 이전의 값을 돌려준다. 따라서 ++42 평가시 42같은 원시 값에 직접 부수효과를 일으킬 수는 없으므로 ReferenceError가 일어난다.
a++
를 ()로 감싸면 후위 부수 효과를 캡슐화 할 수 있다고 착각 하는 경우가 있다.
var a = 42;
var b = a++;
a; // 43
b; // 42
안타깝지만 ()로 둘러싼다해도 부수효과 발생 이후 재평가된 새 표현식을 만들어내는 건 불가능하다. 설사 가능하다 하더라도 a++는 42를 먼저 반환하므로 ++ 부수효과 이후 ㅐㅈ평가가 가능한 연산자가 따로 있지 않은 한, 이 표현식에서 43을 반환받을 도리는 없다. 그래서 b에는 43이 할다되지 않는다.
하지만 방법이 아주 없는 건 아니다. 문을 나열하는 콤마 연산자 를 사용하면 다수의 개별 표현시을 하나의 문으로 연결 할 수 있다.
var a = 42,
b;
b = (a++, a);
a; // 43
b; // 43
다른 예시를 보자.
function vowels(str) {
var matches;
if (str) {
// 모든 모음을 추출한다.
matches = str.match(/[aeiou]/g);
if (matches) {
return matches;
}
}
}
vowels("Helloe World"); // ["e", "o", "o"]
잘 작동하는 코드다 많은 개발자가 이렇게 작성한다. 할당 연산자의 부수효과를 잘 활용하면 다음 과 같이 2개의 if문을 하나로 간단히 합칠 수 있다.
function vowels(str) {
var matches;
if (str && (matches = str.matches(/[aeiou]/g))) {
return matches;
}
}
vowels("Helloe World"); // ["e", "o", "o"]
두 조건이 서로 분명히 연관되어 있음을 잘 보여주기 때문에 나는 후자를 더 선호하느 편이다. 물론 어떤 스타일을 선호할지는 순전히 개인 취향에 달려 있다.
참고
- You Don't Know JS - 타입과 문법, 스코프와 클로저( 한빛 미디어 )
'JAVASCRIPT' 카테고리의 다른 글
[JS][문법] 연산자 우선순위 (0) | 2022.02.14 |
---|---|
[JS][문법] 콘텍스트 규칙 (0) | 2022.02.14 |
[JS][문법] 문과 표현식 (0) | 2022.02.13 |
[JS][강제변환][마무리] 추상 관계 비교 (0) | 2022.02.13 |
[JS][강제변환] 동등비교 : 희귀 사례 (2) (0) | 2022.02.13 |
댓글