본문 바로가기
공부/자바스크립트

[js] "1" + "1" = "11"인 이유

by 야옹아옹 2022. 11. 5.


📢 개인 공부용으로 작성된 내용임으로 잘못된 부분이 있을 수 있습니다.

잘못된 부분을 알려주시면 빠른 시일 안에 수정하겠습니다. 감사합니다.


자바스크립트에서 "1""1"을 더하면 "11"이 된다. 그러나 "1" - "1"은 0이 된다. 이렇게된다는 것은 알지만, 왜 그런지는 잘 모르겠어서 이번 주 블로그 주제로 결정했다. 

+ 연산자와 - 연산자

먼저, +연산자와 -연산자가 무엇이 다른지 찾아봤다.

Addition + 연산자

The addition operator (+) produces the sum of numeric operands or string concatenation.
- mdn

MDN을 보면 + 연산자는 가지 기능을 가지고 있다.

  • 숫자를 더하는 기능
  • 문자열을 이어붙이는 기능

Subtraction - 연산자

The subtraction operator (-) subtracts the two operands, producing their difference.
- mdn

MDN을 보면 -연산자는 두 연산자의 차이를 구하는 하나의 기능만 가지고 있다.

두 연산자의 차이점

위 글을 보면 알겠지만, + 연산자는 숫자를 계산하는 기능 외에 문자열을 이어붙이는 기능도 가지고 있다.

따라서 +연산자를 사용할 경우 어떤 기능을 사용해야하는지 구분해야된다. (엔진뿐만아니라 우리도..)

MDN 페이지의 Addition 설명

무서운 영어를 제외하고 불릿 리스트의 첫번째 글을 읽어보면,

  • 만약 한쪽 피연산자가 문자열이면 다른 한쪽 피연산자도 문자열로 변환하고, 그 두 문자열을 이어붙인다고 써있다.
따라서, + 연산자한쪽 피연산자string 타입인 경우 다른 한쪽 피연산자를 문자열로 변환해 덧셈 기능이 아니라 문자열을 이어붙이는 기능을 수행한다!

이를 자바스크립트 스펙 사이트를 보면서 조금 더 자세히 알아보기로 했다.


자바스크립트 스펙

아직 스펙을 보는 방법을 잘 알지 못하기 때문에 이해하는 만큼 정리한 내용입니다.

The Addition Operator (+)

자바스크립트 스펙 사이트에서 +연산자에 대해 확인해보면 MDN 설명과 같다.

+연산자가 하는 기능은 string concatenation과 numeric addtion이다.

+ 연산자에 대한 영어 설명

그리고 Return에 EvaluateStringOrNumbericBinaryExpression 호출을 한다고 쓰여있다. 클릭해서EvaluateStringOrNumbericBinaryExpression가 무엇인지 확인해보자.

EvaluateStringOrNumbericBinaryExpression

EvaluateStringOrNumbericBinaryExpression에 대한 설명

읽어본다면 추상 연산인 EvaluateStringOrNumbericBinaryExpression은 피연산자 2개와 opText(연산자)를 인수로 사용해서 문자열, BigInt, number를 포함한 일반 완료(normal completion) 또는 abrupt completion을 반환한다고 써있다.

EvaluateStringOrNumbericBinaryExpression은 호출 시, 5가지 과정을 따른다. 

5가지 과정을 내 나름대로 이해해봤다.

  1. 오른쪽 피연산자를 평가
  2. lval에 오른쪽 피연산자 값
  3. 왼쪽 피연산자를 평가
  4. rval에 왼쪽 피연산자 값
  5. ApplyStringOrNumbericBinaryOperator에 위에서 구한 lval, rval 그리고 opText(연산자, 여기서는 +)를 인수로 전달해 얻은 결과를 Return한다.

새로운 함수인 ApplyStringOrNumbericBinaryOperator가 등장했다. 따라서 ApplyStringOrNumbericBinaryOperator로 클릭해 이동하자.

ApplyStringOrNumbericBinaryOperator

ApplyStringOrNumbericBinaryOperator에 대한 설명

확인해보면 lval, opText, rval을 인수로 받아 BigInt, number을 포함하는 일반 완료(normal completion) 또는 throw competion을 반환한다는 이야기같다.

그리고 여기서 opText에는 **,  *, /, %, +, -, <<, >>, >>>, &, ^, | 값들이 들어온다는 것을 확인할 수 있다.

  • 즉, ApplyStringOrNumbericBinaryOperator는 위 연산자들을 사용하면 호출되는 함수라고 생각할 수 있다.
  • 따라서 -연산자를 사용했을 때도 결론적으로 ApplyStringOrNumbericBinaryOperator가 호출될 것이다.

ApplyStringOrNumbericBinaryOperator가 처리하는 과정은 아래와 같다.

ApplyStringOrNumbericBinaryOperator가 수행하는 스텝

정말 길지만 우리가 확인해야하는 부분은 가장 위에있는 1번째 경우(opText가 +인 경우)이다.

연산자가 +인 경우에 하는 처리

위 이미지를 보면, opText가 +인 경우 즉, +연산자를 사용한 경우에 오른쪽 피연산자와 왼쪽 피연산자를 원시형 타입으로 만든다. 

이때, 피연산자 둘 중 하나라도 string 타입인 경우, 다른 쪽 피연산자를 string 타입으로 만든다.

그리고 덧셈 연산을 하지않고 두 피연산자를 string-concatenation 문자열로 이어붙인 후에 return 한다.

만약 피연산자 둘 다 string 타입이 아닌 경우는 lval과 rval에 각각 값을 넣은 후에 아래의 이어지는 과정을 통해 숫자 연산을 진행한다.

결론

  • 자바스크립트 “1”+”1”이 “11”이 되는 이유는 +연산자의 기능이 두 가지이기 때문이다.
  • 코드가 실행되기 위해 해석되면서, +연산자의 피연산자의 타입이 string인 경우에는 숫자를 더하는 연산이 아니라 문자열로써 concatenation하라고 스펙(문법서)에 쓰여있기때문에 이렇게 작동하는 것이다.
  • - 연산자는 스펙에서 그런 해당 사항이 없고, 문자열로 입력되더라도 3번과 4번 과정에서 ToNumeric을 통해 숫자 타입으로 변환해준다. 따라서 잘 계산되는 것이다.

연산자가 +가 아닌 경우, 바로 Numeber 타입으로 처리


지금은 너무 깊게 들어가기에는 시간적으로 낭비라고 생각해서 간략하게만 이해했지만 나중에는 좀 더 언젠가는 하나씩 읽어서 조금 더 자세히 내용을 정리하고 싶다.

댓글