콘텐츠로 건너뛰기

개발자를 당황하게 만드는 자바스크립트 형변환

자주 들르는 커뮤니티에서 자바스크립트의 형변환으로 인한 여러 사례로 재미있는 글이 올라온 걸 봤습니다. 비슷한 문제로 생각지 못한 엉뚱한 곳에서 발생하는 문제를 종종 경험했기에 충분히 이해도 됩니다. 그 이상한 일들이 왜 일어나는지에 대해 이 글을 통해 정리 해 보려 합니다.

자바스크립트 동등 비교연산

자바스크립트의 자동 형변환을 이해 해야 당황하지 않음
자바스크립트의 자동 형변환을 이해 해야 당황하지 않음
console.log(0 == "0");     // true
console.log(0 == []);      // true

// "0" == 0 == [] 이라면?

console.log("0" == []);    // false

0 == “0” 이 true이고 0 == [] 도 true라면 “0” == [] 가 true가 아닐까? 하지만 결과는 false 입니다. 어찌 된 일일까요?

자바스크립트에서는 동등 비교연산(== 또는 !=)을 수행 할 때, 두 피연산자의 타입이 다른 경우 두 피연산자를 동일한 타입으로 변환 후 비교연산을 수행합니다.

타입 변환에 대한 규칙은 다음과 같습니다.

  • 숫자와 문자열 비교 시 문자열을 숫자로 변환
  • 숫자 또는 문자열과 객체 비교 시 객체를 기본 데이터 타입으로 변환

여러가지 타입 변환에 대한 규칙이 있지만 이번 문제에 적용되는 규칙은 위의 두 가지 입니다. (ECMAScript Language Specification – Abstract Equality Comparison Algorithm)

이 규칙을 알고 다시 한번 풀어서 비교 해 보겠습니다.

// 1. 숫자와 문자열 비교는 문자열을 숫자로 변환
// console.log(0 == "0");         // true
console.log(Number("0"));         // 0
console.log(0 == Number("0"));    // 0 == 0 의 결과 true

// 2. 숫자와 객체 비교는 객체를 기본 데이터 타입으로 변환
// console.log(0 == []);          // true
console.log(Number([]));          // 0
console.log(0 == Number([]));     // 0 == 0 의 결과 true


// "0" == 0 == [] 이라면?
// 3. 문자열과 객체 비교는 객체를 기본 데이터 타입으로 변환
// console.log("0" == []);        // false
console.log(String([]));          // ""
console.log("0" == String([]));   // "0" == "" 의 결과 false

==, != 동등 연산 시 내부적으로 비교를 위해서 형변환이 이루어 집니다. 만약 형변환 없이 비교를 수행하고 싶다면 일치 연산자(===)를 사용하면 됩니다. 일치 연산자의 경우 비교되는 피연산자들의 타입이 다르면 false를 반환합니다. 일치가 아닌 불일치를 확인하고 싶다면 !== 를 사용하면 됩니다.

console.log(0 === "0");     // false
console.log(0 === []);      // false
console.log("0" === []);    // false

자바스크립트의 더하기(+) 연산자

쉽고 이해하기 쉬운 자바스크립트
쉽고 이해하기 쉬운 자바스크립트
console.log("11" + 1);     // 111
console.log("11" - 1);     // 10

자바스크립트는 정말 쉽고 이해하기 쉬운 언어입니다. 그런데 “11” + 1은 “111”이라는 결과가 나오고 “10” – 1은 10이라는 결과가 나옵니다. 갑자기 이해하기 어려운 언어로 변했습니다.

이런 이해하기 어려운 결과가 나오는 데는 자바스크립트에서 더하기(+) 연산자가 동작하는 방식을 이해해야 합니다. 자바스크립트에서 더하기(+) 연산자는 문자열을 연결하거나 숫자의 덧셈 연산을 합니다. (ECMAScript Language Specification – The Addition operator ( + ))

console.log("11" + 1);     // 111
console.log("11" + "1");   // 111
console.log(11 + 1);       // 12

더하기(+) 연산자의 피연산자가 모두 문자열이라면 문자열을 연결하는 연산을 수행합니다. “가나다라” + “마바사”인 경우에 “가나다라마바사” 결과가 나옵니다. 피연산자가 모두 숫자라면 우리가 알고 있는 덧셈 연산을 수행합니다. 1 + 1은 2의 결과가 나옵니다.

하지만 피연산자가 문자열과 숫자 또는 다른 타입의 객체가 함께 사용되는 경우에는 모두 문자열로 변환하여 문자열 연결 연산을 수행하게 됩니다.

// 1을 문자열로 변환하면 1이기 때문 같은 결과가 나온다.
console.log(String(1));                 // "1"
console.log("11" + String(1));          // "111"
console.log("11" + 1);                  // "111"

// [1,2,3]도 문자열로 변환되면 "1,2,3" 형태가 되기에 아래 결과가 나온다.
console.log(String([1,2,3]));           // "1,2,3"
console.log("11" + String([1,2,3]));    // "111,2,3"
console.log("11" + [1,2,3]);            // "111,2,3"

// null도 문자열로 변환하여 연산
console.log(String(null));              // "null"
console.log("11" + String(null));       // "11null"
console.log("11" + null);               // "11null"

빼기(-) 연산자는 피연산자에 숫자 타입이 아닌 다른 타입의 객체가 있는 경우 숫자 타입으로 형변환 하여 뺄셈 연산을 수행합니다.

// "11"문자열을 숫자로 변환하여 연산
console.log(Number("11"));         // 11
console.log(Number("11") - 1);     // 10
console.log("11" - 1);             // 10

// null도 숫자로 변환하여 연산
console.log(Number(null));         // 0
console.log(1 - Number(null));     // 1
console.log(1 - null );            // 1

// boolean 타입도 예외는 없다
console.log(Number(true));         // 1
console.log(1 - Number(true));     // 0
console.log(1 - true);             // 0

이제 당황하지 마세요

자바스크립트 참 쉽죠?
자바스크립트 참 쉽죠?

이제 자바스크립트의 몇 가지 자동 형변환에 대한 동작 방식을 알게 되었습니다. 앞으로는 자동 형변환으로 인해 나오는 결과에 당황하지 않을 수 있게 되었습니다.

참 쉽죠?


답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다