자바스크립트에는 값을 비교하는 방식이 여러 방식으로 할 수 있다는 것을 알 것이다.
뭐 작게 보면 ==, ===, Object.is 이런 것들이 있을 것이고, typeof, instanceof를 이용하는 등... 로직을 구성하여 비교하는 나열하기가 힘들 정도로 여러 방식이 있을 것이다.
혹시 indexOf를 사용 해본적이 있나? 배열과 문자열에서 기본적으로 제공하는 함수이며, 꽤나 친숙한 함수 일 것이다.
그렇다면 includes는 사용 해보았나? indexOf는 값의 위치를 알려주기 때문에, 꽤 불편 하다. 아래 같은 경우 말이다.
const keyWord = 'hello'
const helloWorld = 'hello world'
if ( helloWorld.indexOf(keyWord) ) {
console.log('indexOf!') // 실행 되지 않음.
}
if ( helloWorld.includes(keyWord) ) {
console.log('includes!') // 실행 됨
}
그래서 아마 값이 있는지 확인만 하는 경우 includes를 사용 하는 경우가 많을 것이다. 하지만 특정 위치가 필요한 경우 indexOf를 사용 할 것이다.
여기서, indexOf 와 includes가 같은 로직으로 값을 확인하는 것이라 착각한다면... 문제가 생길 여지가 생겨 버린다.
단적인 예로, 배열에는 존재 하지만, 배열에서 위치를 못 찾는 경우가 생기는 경우가 있다.
아래 코드를 꼭 실행 시켜보도록 하자.
const arr = [1, 2, 3, 4, NaN]
if( arr.includes(NaN) ) {
console.log(`NaN이 ${arr.indexOf(NaN)}에 있습니다.`)
// NaN이 -1에 있습니다.
}
"NaN이 -1에 있습니다." 이게 대체 무슨 일이 생긴 걸까? includes 함수는 NaN이 있어서 true를 리턴 하였지만...
indexOf는 NaN을 찾을 수가 없어서 -1을 리턴 하였다. 무슨 일이 생긴 걸까?
indexOf
일단 indexOf를 확인 해보자.
console.log( [0].indexOf(false) ) // -1
console.log( [NaN].indexOf(NaN) ) // -1
console.log( [0].indexOf(-0) ) // 0
console.log( 0 === false ) // false
console.log( NaN === NaN ) // false
console.log( 0 === -0 ) // true
console.log( 0 == false ) // true
console.log( NaN == NaN ) // false
console.log( 0 == -0 ) // true
console.log( Object.is(0, false) ) // false
console.log( Object.is(NaN, NaN) ) // true
console.log( Object.is(0, -0) ) // false
// false / false / true - indexOf
// false / false / true - ===
// true / false / true - ==
// false / true / false - Object.is
위의 결과를 보면 indexOf는 === 을 따르는 것을 볼 수 있다. 당연하게도 lastIndexOf도 또한 같은 결과를 따른다.
includes
console.log( [0].includes(false) ) // false
console.log( [NaN].includes(NaN) ) // true
console.log( [0].includes(-0) ) // true
console.log( 0 === false ) // false
console.log( NaN === NaN ) // false
console.log( 0 === -0 ) // true
console.log( 0 == false ) // true
console.log( NaN == NaN ) // false
console.log( 0 == -0 ) // true
console.log( Object.is(0, false) ) // false
console.log( Object.is(NaN, NaN) ) // true
console.log( Object.is(0, -0) ) // false
// false / true / true - includes
// false / false / true - ===
// true / false / true - ==
// false / true / false - Object.is
includes는 어떠한가? 어떠한 항목과도 일치 하지 않는다. 그렇다면 새로운 방식으로 구성 되었다는 것인데.... 어떤 방식일까?
Object.is
일단 Object.is에 대해서 설명이 필요 할 것 같다. 일단 ==, ===과 다르게 NaN에 대해서 값이 같은 것으로 판단을 해준다. 하지만 아쉽게도, -0, +0에 대해서는 거짓이 나온다.
어떤 로직일까? 일단 이 함수는 SameValue 방식을 사용 한다.
간단하게, 설명하면 ===나머지는 같은 결과이고.
SameValue(+0, -0) // false
SameValue(NaN, NaN) // true
위의 정도만 다른 함수이다.
SameValueZero
위에서 sameValue에 대해서 소개 하였다. 그러면 sameValueZero는 무엇일까? 이름만 보면 SameValue와 갖고 0에 대해서는 같은 값을 리턴 하는 것 같다.
아까의 주석을 다시 한번 확인 해보자.
// 0 vs false / NaN vs NaN / 0 vs -0
// false / true / true - includes
// false / false / true - ===
// true / false / true - ==
// false / true / false - Object.is
sameValue를 사용 하는 Object.is에서 0 vs -0만 true값이 되게 되면 includes와 같은 결과가 나온다.
즉 includes는 sameValueZero를 사용 하는 것을 알 수 있다!
참고 사항
일단 sameValueZero라는 것을 알려주었으니, 사용 하는 곳을 알려주는 것이 맞을 것 같다.
Map의 delete, get, has, set 함수 => set 함수는 key에 대해서 만.
Set의 add, delete, has 함수
const map = new Map()
map.set( NaN, NaN )
map.set( -0, -0 )
console.log( map.has( NaN ) ) // true
console.log( map.has( -0 ) ) // true
console.log( map.has( 0 ) ) // true
console.log( map.get( NaN ) ) // NaN
console.log( map.get( -0 ) ) // -0
console.log( map.get( 0 ) ) // -0
console.log( map.delete( NaN ) ) // -0
console.log( map.delete( 0 ) ) // -0
console.log( map.delete( -0 ) ) // false
const set = new Set()
set.add( NaN )
set.add( -0 )
set.add( 0 )
console.log( set ) // { NaN, 0 }
console.log( set.has( NaN ) ) // true
console.log( set.has( -0 ) ) // true
console.log( set.has( 0 ) ) // true
console.log( set.delete( NaN ) ) // true
console.log( set.delete( 0 ) ) // true
console.log( set.delete( -0 ) ) // false
위의 예시를 보면 NaN에 대해서 잘 찾고 있는 것을 확인 할 수 있으며, +0, -0이 같은 값을 갖는 것을 할 수 있다.
댓글
댓글 쓰기