본문 바로가기
JAVASCRIPT

[JS][강제변환] 동등비교 : null -> undefined, 객체 -> 비객체

by KBS 2022. 2. 12.
728x90

동등비교 : null -> undefined

nullundefined 간의 변환은 느슨한 동등 비교 == 이 암시적 강제변환을 하는 또 다른 예이다. ES5 11.9.3.2-3을 살펴보면

  1. x가 null이고 y가 undefined면 true를 반환한다.
  2. x가 undefined이고 y가 null면 true를 반환한다.

null과 undefined를 느슨한 동등 비교하면 서로에게 타입을 맞춘다(강제변환 한다.). 언어 전체를 눈 씻고 찾아봐도 다른 값은 끼어들 여지가 없다.

즉, nullundefined는 느슨한 동등 비교 시 상호 간의 암시적인 강제변환이 일어나므로 비교 관점에서 구분이 되지 않는 값으로 취급되는 것이다.

var a = null;
var b;

a == b; // true
a == null; // true
b == null; // true

a == false; // false
b == false; // false
a == ""; // false
b == ""; // false
a == 0; // false
b == 0; // false

 

'null <-> undefined' 강제변환은 안전하고 예측 가능하며, 어떤 다른 값도 비교 결과 긍정 오류를 할 가능성이 없다. nullundefined을 구분되지 않는 값들로, 결국 동일한 값으로 취급하는 강제변환은 권장하고 싶다.

var a = doSomething();

if (a == null) {
  // ...
}

 

a == null의 평가 결과는 doSomething()null이나. undefined를 반환할 경우에만 true, 이외의 값이 반환되면 false다.

강제변환이 내키지 않아 명시적으로 체크하겠다고 다음처럼 작성한 코드는 슬데없이 흉하기만 하다.

var a = doSomething();

if(a ==== undefined || a === null){
  // ...
}

 

a == null 같은 코드는 가독성 좋고 안전하게 작동하는 암시적 강제변환의 일례이다.

동등비교 : 객체 -> 비객체

객체/함수/배열과 단순 스칼라 원시 값의 비교는 ES5 11.9.3.8-9에서 다룬다.

  1. Type(x)가 String 또는 Number고 Type(y)가 객체라면 x == ToPrimitive(y)의 비교 결과를 반환한다.
  2. Type(y)가 String 또는 Number고 Type(x)가 객체라면 ToPrimitive(x) == y의 비교 결과를 반환한다.
var a = 42;
var b = [42];

a == b; // true

 

[42]ToPrimitive 추상 연산 결과 "42"가 된다. 그리고 "42" == 42 ---> 42 == 42이므로 a, b는 동등하다.

원시 값을 감싼 객체 래퍼를 안꺼풀 벗겨 원시 값을 반환하는 과정이다. 언박싱은 == 알고리즘의 ToPrimitive 강제변환과 관련되어 있다.

var a = "abc";
var b = Object(a); // 'new String(a)'과 같다.

a === b; // false
a == b; // true

 

b는 ToPrimitive 연산으로 "abc"라는 단순 스칼라 원시 값으로 강제변환되고 이 값은 a와 동일하므로 a == b는 true가 된다.

하지만 항상 그런 것은 아니다. == 알고리즘에서 더 우선하는 규칙 때문에 그렇지 않는 경우 들도 있다.

var a = null;
var b = Object(a); // 'Object()'와 같다.
a == b; // false

var c = undefined;
var d = Object(c);
c == d; // false

var e = NaN;
var f = Object(e); // 'new Number(e)'와 같다.
e == f; // false

 

nullundefined는 객체 래퍼가 따로 없으므로 박싱할 수 없다. 그래서 Object(null)Object()로 해석되어 그냥 일반 객체가 만들어진다.

NaN은 해당 객체 래퍼인 Number로 박싱되지만, ==를 만나 언박싱되면 결국 조건식은 NaN == NaN이 되어 결과는 false이다(NaN은 자기 자신과도 같지 않다.).


참고

  • You Don't Know JS - 타입과 문법, 스코프와 클로저( 한빛 미디어 )
728x90

댓글