ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트의 빈 배열([])은 빈 문자열(""), 0이지만 boolean일 땐 true로 변환되는 이유
    개발/자바스크립트로의 깊은 잠수 2026. 4. 1. 21:33

    JavaScript의 타입 변환 시스템은 봐도봐도 새롭습니다.

    암묵적 타입 변환이 일어날 수 있어서, 결과를 예측하기 어려운 경우가 많아요.

    그 중에서도 특히 헷갈리는, 빈 배열 (`[]`)의 타입 변환을 정리해 보았습니다.

     

     

    빈 배열을 문자열과 숫자로 변환하기

    먼저 빈 배열을 문자열(string)과 숫자(number)로 각각 변환해 보겠습니다.

     

    객체가 string, number같은 원시값(primitive)으로 변환될 때, 자바스크립트 엔진은 ToPrimitive 추상 연산을 수행합니다.

    해당 객체에 대해서 `.toString()`과 `.valueOf()`를 순서대로 시도해요.

     

    객체 중에서도, 배열의 `.toString()`은 내부적으로 `Array.prototype.join()`을 먼저 호출합니다.

    빈 배열을 join하면 빈 문자열 (`""`)이 반환됩니다.

    그래서 빈 배열을 string으로 변환하면 빈 문자열입니다.

    [].toString(); // "" (내부적으로 join을 먼저 호출한다)
    [].join();     // ""

     

    마찬가지로 빈 배열을 number로 변환할 때, ToPrimitive 추상 연산이 수행되므로 내부적으로 `toString()` 호출이 먼저 이루어집니다.

    따라서 빈 배열은 빈 문자열이 되고, 빈 문자열은 다시 숫자 0이 됩니다.

    Number([])  // [] → "" → 0
    Number("")  // 0

     

     

    근데 왜 Boolean으로 변환하면 true인가?

    참 이상합니다.

    빈 배열의 string 변환 결과인 빈 문자열은 Boolean 변환했을 때 false입니다.

    빈 배열의 number 변환 결과인 0도 Boolean 변환했을 때 false입니다.

    그런데 빈 배열은 Boolean 변환했을 때 true입니다.

    Boolean(""); // false
    Boolean(0);  // false
    Boolean([]); // true

     

    놀랍게도 ToBoolean 변환은 ToPrimitive를 거치지 않습니다.

    (Boolean은 원시값이지만, 다른 원시값이랑은 별개로 또다른 타입 변환 방식을 갖고 있는 것입니다..!)

     

    ToBoolean 규칙은 아주 단순합니다.

    false로 평가되는 값은 딱 정해져 있습니다.

    false, 0, -0, 0n, "", null, undefined, NaN

     

    이외의 값들은 모두 true로 평가됩니다(!)

     

    그래서 빈 배열은 Boolean으로 변환하면 true입니다.

     

     

    왜 boolean만 차별해

    그래서, 왜 boolean만 다른 원시값(primitive)들과는 다른 타입 변환 체계를 가지게 된 걸까요?

     

    ECMAScript 명세 전문 저술가인 Axel Rauschmayer 박사의 글에 따르면, 객체에 toBoolean() 같은 메서드를 허용하는 것은 성능 문제를 야기할 수 있기 때문에 객체는 항상 true가 되도록 설계되었습니다.

     

    근본적인 원인은 단축 평가 연산자(`&&, ||`) 때문입니다.

    `&&`는 평가될 때 boolean을 반환하지 않고, 피연산자 원본 값을 그대로 반환합니다.

    그래서 연속적인 `&&`는 원본 값이 계속 평가되어야 하는 경우를 유발할 수 있습니다.

     

    예시를 들어볼까요?

    만약에, `toBoolean()`메서드의 커스터마이징이 가능해서 `new Boolean(false)` 같은 객체가 false로 변환된다고 가정해 봅시다.

     

    그러면 아래와 같은 단축 평가 표현식이 있을때,

    new Boolean(false) && 1 && true;

     

    이 표현식을 평가하기 위해서 다음과 같은 과정이 진행됩니다.

    new Boolean(false) && 1
    // 먼저 new Boolean(false)를 boolean으로 평가하기 위해 toBoolean()을 호출합니다.
    // false라는 것을 알아냅니다.
    // 하지만 평가 이후에, 평가된 값 false가 아닌 원본 값 new Boolean(false)이 반환됩니다.
    
    new Boolean(false) && true
    // 그러면 또 toBoolean()을 호출해야 합니다!

     

    이처럼 연쇄적으로 단축 평가가 이어졌을 때, 계속해서 객체 원본을 변환하는 비싼 변환이 발생하게 되죠.

    그래서 ECMAScript 1을 설계할 때 객체가 boolean 변환을 직접 설정(configure)할 수 없도록 결정되었다고 합니다.

     

    그럼 왜 toString이나 valueOf는 괜찮아요?

    + 나 == 같은 연산자는 값의 평가 결과를 사용합니다.

    원본 객체가 다음으로 전달되지 않죠.

    [] + 1 + 2
    // [] → "" (변환 결과인 ""이 다음으로 넘어감)
    // "" + 1 → "1"
    // "1" + 2 → "12"
    // []는 한 번만 변환되면 끝

     

    그래서 toString은 괜찮고, toBoolean은 안되는 거랍니다!

     

     

     

    참조

    Ecma International. (2025). ECMAScript® 2026 Language Specification (ECMA-262, 15th ed.). TC39. https://tc39.es/ecma262/#sec-toprimitive
    Rauschmayer, A. (2013, August 20). Why all objects are truthy in JavaScript. 2ality. https://2ality.com/2013/08/objects-truthy.html

     

    댓글

Copyright 2022. ProdYou All rights reserved.