loading
반응형

자바스크립트(javascript)

동등 연산자 (==), (===) 어떤 방식으로 비교를 하길래 혼란스럽게 하는가

 

순번 링크페이지 아래 제목을 클릭하면 해당 링크페이지로 이동 됩니다.
1 JS - 자바스크립트(javascript) 동등 연산자 ==, === 이상하다, 혼란스럽다 - (1)
2 JS - 자바스크립트(javascript) 동등 연산자 ==, === 이상하다, 혼란스럽다 - (2)
3 JS - 자바스크립트(javascript) 동등 연산자 ==, === 이상하다, 혼란스럽다 - (3)

 

▶ Loose(느슨한) Equals & Strict(엄격한) Equals

 

💻 문자열 Boolean (==), (===) 비교 

JS - 자바스크립트(javascript) 동등 연산자 ==, === 이상하다, 혼란스럽다 - (1)

 

이전 글에 이어 문자열과 Boolean 값을 비교할 때, 느슨한 등호를 사용하면 강제 형 변환이 일어나

뜻하지 못한 결과를 얻었다. 이러한 결과를 피하려면 엄격한 등호를 사용하면 되는데,

 

// 느슨한 등호를 사용할 시

var string = '100';
var num = 100;

if(string == num){
	console.log('yes');
}




// 엄격한 등호를 사용할 시

var strString = '101';
var numNumber = 101;

if(strString === numNumber){
	console.log('yes_ok');
}

 

이렇게 엄격하게 비교를 구문을 활용하면, 우리가 생각하는 일반적인 결론을 얻을 수 있다.

strString의 변수는 '101'이라는 문자열 숫자를 담고 있고,

numNumber의 변수는 숫자 101을 담고 있다.

 

엄격한 등호(===)를 사용하여 비교를 했을 때, 두 개의 변수의 값은 같지 않기 때문에

console.log를 출력하지 못할 것이다. 여기까지가 이전 글에서 정리했던 내용이다.

 

 

💻 null과 undefined (==), (===) 비교 

ECMAScript5 spec 11.9.3 ☜ 링크

ECMAScript5 spec 11.9.3.2 ~ 11.9.3.3 나온 내용을 보면,

 

2. If x is null and y is undefined, return true
(x  가 null이고 y정의되지 않은 경우 true 반환)

3. If x is undefined and y is null, return true
(x정의되지 않고 ynull 이면 true를 반환)

 

그럼 이제 예제를 통해서 확인해보자.

var NULL = null;
var UND;

if(NULL == UND){
	console.log('yes'); // 출력
}

if(NULL == null){
	console.log('yes'); // 출력
}

if(UND == null){
	console.log('yes'); // 출력
}

//=========================// 비교 위 아래!


if(NULL == false){
	console.log('yes'); // NO! 출력 안됨
}

if(UND == false){
	console.log('yes'); // NO! 출력 안됨
}

if(NULL == ""){
	console.log('yes'); // NO! 출력 안됨
}

if(UND == ""){
	console.log('yes'); // NO! 출력 안됨
}

if(NULL == 0){
	console.log('yes'); // NO! 출력 안됨
}

if(UND == 0){
	console.log('yes'); // NO! 출력 안됨
}

 

 

예제를 확인해보면 ECMAScript5 spec에 정의된 내용처럼 위 3개의 예제는 전부 if문을 통과하여

console.log를 출력을 한다. 둘 중 하나가 null이고 또 하나는 undefined 일 때 true를 반환하기 때문에

 

느슨한 등호(==) 비교를 할 때 true가 되어 console.log의 'yes'가 출력이 된다.

즉, 느슨한 등호(==)의 비교가 nullundefined 일 경우에만 동등성으로 보기 때문이다.

 

그래서 nullundefined(==) 비교 시에 같을 수밖에 없다.

그럼 아래 6개 예제를 보자.

 

전부 if문 통과하지 못하고, console.log가 출력이 안된다.

느슨한 등호(==)강제 형 변환을 시도한다고 이 전 글에서 얘기한 바 있다.

 

그럼 강제 형 변환이 되어서 if문을 통과해서 console.log 찍어야 하지 않나?라는 질문을 할 수 있다.

하나로 예로 들자면 NULL 변수가 강제 형 변환이 진행이 되어 false 가 되는데, 

 

그럼 저 if문을 통과하여 console.log 'yes'를 출력해야 하지 않느냐?라는 질문이다.

근데 아까도 말했던 것과 같이 답은 똑같다.

 

다시 말하자면 느슨한 등호(==) 이 놈은 nullundefined 비교할 경우에만 true를 반환하는 거다.

저렇게 false 라던지, 0 값이라던지, 값이 없는 문자열 이라던지의 비교에서는 동등하지가 않다는 것이다.

 

 

자 이제 실제 개발에서 실수를 좀 하는 부분이긴 한데 과장을 좀 보태서 아래와 같은 예제의 코드를

만들었다고 가정하고 설명하겠다.

function outputData(number){
  if(number > 10){
    return true
  }
}


var val = outputData(4);

console.log(val); // undefined

// 느슨한 등호 (==)
if(val == null){
	console.log('yes');
}

if(val == false){
	console.log('yes');
}


// 엄격한 등호 (===)
if(val === null){

}

if(val === false){

}

 

outputData라는 매개변수에 숫자 10 이상을 넣으면 true를 반환하는 함수를 만들었다 가정하고,

10 값 이상만 넣으면 true 값으로 무엇인가 코딩을 해야 할 상황이라 가정하자.

 

그러나 10 미만의 숫자가 매개변수로 들어갔고, 결국 outputData 함수의 반환 값은 아무것도 없다.

즉, outputData 함수에서 10 미만일 경우에의 반환 값을 지정해줬어야 하는데 실수로 그만 10 이상의 것만

true의 값만 반환받을 생각만 하고 10 미만일 경우의 반환 처리를 안 해줬던 것이다.

 

개발자는 이 사실을 모르고 if문 구문으로 val 변수의 결과 값이 null 일 경우에만 무엇인가를

해야만 하는 코드를 넣어야 하는 부분이 console.log('yes')를 찍어야 하는 부분이라고 가정하자.

 

그런데 여기서 저 console.log의 'yes' 부분은 출력이 된다.

개발자는 이제 여기서 혼동이 온다.. 분명 저 outputData 함수에선 null이라는 값을 반환한 적이 없는데..

 

if문이 통과가 되어 console.log의 'yes'를 출력하고 있으니 말이다....

또 다른 예 아래 if문을 확인해보자.

 

이번엔 개발자가 저 함수의 반환 값이 undefined라는 걸 알고 코드를 이렇게 개발했다고 가정해보자.

val 변수가 false 일 때 무엇인가를 행위해야 하는 코딩을 해야 하는데... 이 if문은 통과하질 못한다.

 

이때 개발자는 혼란스러울 것이다.. 실제 내가 그랬음...

당연 반환받은 값이 없겠거니 당연히 false 이겠거니... 했지만 저 if문은 통과가 안된다...

 

이처럼 느슨한 등호(==) 이놈은 null, undefined의 경우일 때 true를 반환하므로, 사용할 땐

엄격한 등호(===) 이놈을 쓰자.

 

반응형

 

 

💻 object 와 object가 아닌 것 (==), (===) 비교 

이번엔 객체와 객체가 아닌 (==) 등호로 비교를 해보자.

이번엔 기가 찰 것이다.

 

우선 예제를 확인 하기전에 object와 object가 아닌 것에 대한 느슨한 등호(==) 비교 처리는 어떻게 정의가 되어있는지 ECMAScript5 spec을 먼저 확인하고 가자.

 

ECMAScript5 spec 11.9.3 ☜ 링크

이 내용의 8, 9번 내용을 보면되는데 (ECMAScript5 spec 11.9.3.8 ~ 11.9.3.9)

8. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
(Type(x) 가 String 또는 Number 이고 Type(y)가 Object 이면 Type(y)에 대한 ToPrimitive 규칙에 의한 추상 형 변환을 시도한 후 Type(x)와 느슨한 등호(==) 비교를 한다.)

9. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.
(Type(x)가 Object 이고 Type(y)는 String 또는 Number 타입인 경우 Type(x)에 대한 ToPrimitive 규칙에 의한 추상 형 변환을 시도한 후의 결과 값과 (==) 느슨한 비교를 한다)

 

대충 ECMAScript5 사양의 내용을 살펴보면 이렇다.

암튼 요약 하자면 오브젝트와 오브젝트가 아닌 것끼리 느슨한 등호(==) 비교를 하면

 

ToPrimitive라는 추상 형 변환이라는 규칙에 의해 형 변환을 시도하는데

무엇이? 형변환을 시도? Object 인 객체

 

즉, Object 객체가 ToPrimitive라는 추상 형 변환 규칙에 의해 형 변환을 시도한다!라고 생각하면 된다.

 

자 이제부터 기가 찰 만한 예제를 확인해보자.

var num = 100;
var arr = [100];

if(num == arr){
	console.log('yes'); // 출력 될까요?
}

 

이 예제를 쓰는 나도 황당하지만... 저거 'yes' 출력 된다...

기가 찬다.

 

이 형 변환에 대해서 쓴 글을 다 보면 저게 왜 저렀는지 이해할 순 있는데,

아무것도 모르는 상태라면 정말 어이가 하늘을 찌를 것이다.

 

다시 이 전 글에 형 변환에 대해 글을 쓴 게 있으니 그 글을 참고하도록 하자.

암튼 저 arr 이란 변수는 배열이지만 자바스크립트에서는 배열도 객체이다.

 

그러므로 저 arr 변수는 ToPrimitive라는 추상 형 변환 규칙에 의해 형 변환된 후에

숫자 100 이 담긴 num이라는 변수와 느슨한 등호(==) 비교를 하면 둘이 같다.

 

그러므로 'yes'가 출력이 된다.

 

또 다른 예제를 살펴보자.

이것도 기가 찰 것이다.

var stringNum = '100';
var val = Object(stringNum); // 명시적 형 변환 시도

if(stringNum == val){
	console.log('yes'); // 출력 될까요?
}

if(stringNum === val){
	console.log('=== yes'); // 출력 될까요?
}

 

이건 어떨까? 자 하나씩 따져보자.

stringNum이라는 변수는 문자열 숫자 '100' 을 담고 있는 변수이고,

val 변수는 stringNum 이라는 변수를 오브젝트로 형 변환하여 담았다.

 

결국 요약하자면,

stringNum 변수는 문자열을 담고 있는 변수,

val 변수는 Object 객체이다.

 

그런데 느슨한 등호 (==) 비교를 해봤더니 같다고 나온다. 'yes'가 출력이 되는 걸 보니 말이다.

그런데 엄격한 등호(===) 비교를 해보면 당연 다르게 나온다.

 

여기서도 하고 싶은 말은 val 변수는 Object라는 객체이지만 느슨한 등호 (==) 비교를 할 때에

ToPrimitive라는 추상적 형 변환 규칙에 의해 형 변환이 일어나는데

 

(==) 비교를 할 때, 값이 같다는 거다.

이것뿐만 아니라 이제 null, undefined는 어떤지 이 예제도 살펴보자.

 

var NULL = null;
var NObj = Object(NULL); // 명시적 형 변환

if(NULL == NObj){
	console.log('yes'); // 출력이 될까요?
}


var UND = undefined;
var UObj = Object(UND); // 명시적 형 변환

if(UND == UObj){
	console.log('yes'); // 출력이 될까요?
}




var Nval = NaN;
var NObj = Object(Nval); // 명시적 형 변환

if(Nval == NObj){
	console.log('yes'); // 출력이 될까요?
}

 

답은 전부 출력이 안된다.

어떤가? 이것은 또 다르지 않은가?

윗글에서 설명한 그대로 이것은 null 이거나 undefined 일 때만 느슨한 등호(==) 

비교는 분명 true반환해서 둘 다 같다고 하는데 

 

이렇게 명시적 형 변환을 시도하여 직접 (==) 느슨한 등호를 비교해봤을 때 왜 이건 다를까?

말 그대로 null이나 undefined 일 때만 느슨한 등호(==)가 같은 거지

 

이렇게 명시적으로 형 변환을 시킨 후에 비교를 하면 다르다.

이 내용은 ECMAScript5 spec 11.9.3의 내용의 규칙들에 의해 (==) 이 느슨한 등호를 수행을 하는 것이다.

반응형

+ Recent posts