[NaN].includes(NaN) === true ?

Jaedeok Kim
aaant
Published in
4 min readJun 1, 2022

code review를 하던 중 이해가 잘 안되는 code를 발견했다.

if (arr.includes(NaN)) {

배열인 arr에 NaN이 있는지 확인하는 code였다.
하지만 NaN과 NaN을 비교하면 false일텐데 저 조건문이 제대로 작동할까? 라는 의문과 함께 바로 개발자 도구를 열어 검증에 들어갔다.

이게 무슨…

includes method가 배열을 돌면서 인자로 입력된 값과 배열의 요소들을 === 로 비교한다면 결과는false 가 나왔어야했다.
하지만 결과는 true, 그 말은 includes method가 === operation과는 다른 방식으로 값을 비교한다는 것이다.
이에 대한 대답은 mdn에서 확인할 수 있었다.

Equality comparisons and sameness

sameValueZero 가 무엇인지 확인하기 전에 javascript가 값을 어떻게 비교하는지 알아보자.
javascript에서 값의 비교를 위해 제공되는 operation과 사용되는 알고리즘은 각각 다음과 같다.

== (Abstract Equality Comparison)

=== (Strict Equality Comparison)
Array.prototype.indexOf, Array.prototype.lastIndexOfswitch 문의 case -matching

Object.is (SameValue)
SameValueZero를 포함한 나머지 알고리즘들이 적용되지 않는 모든 곳

그리고 SameValueZeroSameValue 알고리즘에서 -0+0 이 동일한 값으로 처리하는 로직이 추가된 알고리즘이다.
SameValueZero%TypedArray%ArrayBuffer constructors, MapSet operations, 그리고 String.prototype.includes and Array.prototype.includes 에 ES2016 부터 사용된다.

그래서 왜 NaN이랑 NaN이 같은데?

위에서 두 값의 동등성을 비교하기 위해 사용되는 operation과 알고리즘을 확인했다.
그리고 ECMAScript에서 설명하는 각 알고리즘의 flow를 확인해보면
===에 사용된 Strict Equality Comparison의 경우 두 값이 NaN이면 false를 return하고
includes에 사용된 SameValueZero의 경우 비교되는 두 값이 NaN이면 true를 return하는 것을 확인할 수 있다.

오늘은 javascript의 compare operationscompare algorithms에 대해 알아 봤다. 코드를 작성한 분도 includescompare algorithm을 알고 작성하신건 아니었지만 덕분에 javascript가 값을 어떻게 비교하는지에 대해 알 수 있었다. 적용되는 algorithm에 따라 예기치 못한 bug가 발생할 수도 있어보여 주의가 필요해 보인다.

Reference

--

--

aaant
aaant

Published in aaant

앤트(aaant)는 다른 분야와의 융합을 통해 해결하지 못했던 문제를 해결해 나갑니다. 앤트의 구성원들은 함께 치열하게 고민하고, 소통하며, 솔루션을 최적화합니다. 그 과정들을 함께 나누고자 합니다.