본문 바로가기
JAVASCRIPT

[JS][문법] 표현식의 부수 효과

by KBS 2022. 2. 13.
728x90

표현식의 부수 효과

대부분의 표현식에는 부수 효과가 없다. 예컨데,

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 - 타입과 문법, 스코프와 클로저( 한빛 미디어 )
728x90

댓글