코딩/Javascript

JavaScript 동등 연산자, 일치 연산자 완전하게 이해하기

드리프트 2021. 6. 3. 20:36
728x170

 

평소 JavaScript 코딩 할때 특히 피연산자의 유형이 다른 경우,  동등 또는 일치 연산자가 어떻게 작동되는지 이해하기 어려울 때가 있습니다.

 

정말로 문제인 것은 조건식에서 이런 버그가 발생되고, 심지어는 알아채지 못할때가 더 심각합니다.

 

여기서 동등 연산자는 "==" 처럼 이퀄기호가 2개 있는 것으로 영어로는 equality operator 라고 합니다.

 

반면에 일치 연산자는 "==="처럼 이퀄기호가 3개 있는 것으로 영어로는 identity operator 라고 합니다.

 

이 글에서는 동등 연산자(==), 일치 연산자(===)라는 명칭을 사용할 예정이오니 혼동하지 마시기 바랍니다.

 

이제 본격적으로 자바스크립의 동등, 일치 연산자에 대해 알아 보겠습니다.

 

일단 이 글에서 사용하는 용어에 대해 짚고 넘어가겠습니다.

 

연산자(Operator)는 작업을 나타내는 기호입니다.

 

예를 들어 동등 연산자 ==는 두 값을 비교하고, 일치 연산자 ===는 두 값과 그 유형을 비교하고, 더하기 연산자 +는 두 숫자를 합하거나 두 문자열을 연결합니다.

 

피연산자는 작업의 대상이며 작업이 수행되는 수량입니다.

 

표현식 0 == {}에서 0은 첫 번째 피연산자이고 {}는 두 번째 피연산자입니다.

 

그리고 일단 알고 계셔야 하는 것 중에 JavaScript의 프리미티브 타입은 숫자(number), 문자열(string), 부울(boolean), null 및 undefined 입니다.

 

 

일치 연산자(The identity operator)

 

JavaScript 인터프리터는 먼저 두 피연산자를 동일한 유형(타입)으로 변환합니다.

 

그런 다음 Identity 비교를 실행합니다. Identity 평가 알고리즘 (IEA 룰) === 는,

 

1. 두 피연산자의 유형이 다른 경우, 완전히 같지 않습니다(not strictly equal).

2. 두 피연산자가 모두 null이면 , 완전히 동일합니다(strictly equal).

3. 두 피연산자가 모두 undefined인 경우, 완전히 동일합니다(strictly equal).

4. 피연산자 중 하나 또는 모두가 NaN이면, 완전히 같지 않습니다(not strictly equal).

5. 두 피연산자가 모두 참이거나 모두 거짓이면, 완전히 동일합니다(strictly equal).

6. 두 피연산자가 숫자이고 값이 같으면, 완전히 동일합니다(strictly equal).

7. 두 피연산자가 문자열이고 값이 같으면, 완전히 동일합니다(strictly equal).

8. 두 피연산자 모두 동일한 객체 또는 함수에 대한 참조가 있으면, 완전히 동일합니다(strictly equal).

9. 1~8 외의 다른 모든 경우에 피연산자는, 완전히 같지 않습니다(not strictly equal).

 

알고리즘의 규칙은 심플해 보입니다.

 

동등(일치) 연산자의 NaN은 다른 값과 비교될 때 항상 거짓으로 평가된다는 점이 주목할 만 합니다.

 

몇 가지 예를 살펴 보겠습니다.

 

예제 1

1 === "1" // false, IEA rule 1

피연산자는 다른 유형(숫자 및 문자열)이며 IEA 규칙 1에 따라 동일하지 않습니다.

 

예제 2

0 === 0 // true, IEA rule 6

피연산자는 동일한 타입(숫자)이고 동일한 값을 가지므로 IEA 규칙 6에 따라 엄격하게 동일합니다.

 

예제 3

undefined === undefined // true, IEA rule 3

두 피연산자는 모두 프리미티브 타입인 undefined 이며 IEA 규칙 3을 적용하면 동일합니다.

 

예제 4

undefined === null // false, IEA rule 1

피연산자는 IEA 규칙 1에 따라 타입(유형)이 다르기 때문에 동일하지 않습니다.

 

예제 5

NaN === NaN // false, IEA rule 4

피연산자는 동일한 타입(숫자)이지만 IEA 규칙 4는 NaN과 동일한 것이 없음을 나타냅니다. 결과는 거짓입니다.

 

예제 6

var firstObject = {},
  secondObject = firstObject;
secondObject['name'] = 'Neo';
secondObject === firstObject // true, IEA rule 8

firstObject 및 secondObject 변수는 모두 동일한 객체에 대한 참조이며 IEA 규칙 8에 따라 동등 연산자(===)가 true로 평가됩니다.

 

예제 7

[] === [] //false, IEA rule 9

[] 리터럴은 새 배열 참조를 만듭니다. 두 피연산자는 동일한 타입(객체)이지만 다른 객체를 참조합니다. IEA 규칙 9에 따라 동등 연산자는 거짓으로 평가됩니다.

 

 

객체를 프리미티브 타입으로 변환

 

동등 연산자를 배우기 전의 또 다른 단계는 원시 변환의 대상을 이해하는 것입니다.

 

JavaScript는 객체를 원시 값과 비교할 때 동등 연산자(==)를 사용합니다.

 

일명 OPCA (Object to primitive conversion algorithm) 은,

 

1. valueOf() 메소드가 존재하면 호출됩니다. valueOf()가 프리미티브를 반환하면 객체는 이 값으로 변환됩니다.

2. 다른 경우에는 toString() 메소드가 존재하면 호출됩니다. toString()이 프리미티브를 반환하면 객체는 이 값으로 변환됩니다.

3. 다른 경우 JavaScript에서 오류가 발생합니다. TypeError : Cannot convert object to primitive value

 

valueOf() 메서드를 호출 할 때 대부분의 기본 객체는 객체 자체를 반환합니다.

 

따라서 toString() 메서드가 더 자주 사용됩니다.

 

* Date 객체에 대한 참고 사항 : 프리미티브로 변환 할 때 객체는 toString() 메서드를 사용하여 즉시 문자열로 변환됩니다.

 

규칙 1 이 날짜에 대해서는 적용 안됩니다.

 

일반 JavaScript 객체인 {} 또는 new Object()는 일반적으로 "[object Object]"로 변환됩니다.

 

배열은 "," 구분 기호로 요소를 결합하여 변환됩니다.

 

예를 들어 [1, 3, "four"]는 "1,3, four"로 변환됩니다.

 

 

 

동등 연산자(the equality operator)

 

여기서는 기본 변환 부분에 대한 정체성과 객체를 잘 이해하는 것이 좋습니다.


동등성 평가 알고리즘 (EEA) == 는,

 

1. 피연산자의 유형이 동일한 경우 IEA를 사용하여 완전히 동일한 지 테스트하십시오. 완전히 같지 않으면 같지 않고(aren't equal), 그렇지 않으면 같습니다(equal).

2. 피연산자의 유형이 다른 경우 :

3. 한 피연산자가 null이고 다른 피연산자가 undefined 인 경우, 동일합니다(are equal).

4. 한 피연산자가 숫자이고 다른 피연산자가 문자열이면 문자열을 숫자로 변환합니다. 그리고 나서 비교를 다시 시도합니다.

5. 피연산자가 boolean이면 true를 1로, false를 0으로 변환합니다. 그리고 나서 비교를 다시 시도합니다.

6. 한 피연산자가 객체이고 다른 피연산자가 숫자 또는 문자열이면 OPCA를 사용하여 객체를 기본 형식으로 변환합니다. 그리고 나서 비교를 다시 시도합니다.

7. 다른 모든 경우에는 피연산자가 같지 않습니다(not equal).

 

예제를 통해 알아 봅시다.

 

예제 1

1 == true // true

1. 1 == true (EEA 규칙 2.3을 사용하여 true를 1로 변환)

2. 1 == 1 (연산자는 동일한 유형, 숫자를 가짐. EEA 규칙 1을 사용하여 동등성을 일치성 평가로 변환)

3. 1 === 1 (두 피연산자는 모두 숫자이고 동일한 값을가집니다. IEA 규칙 6에 따라 같음)

4. 결과값은 true임

 

예제 2

'' == 0 // true

1. ''== 0 (한 피연산자는 문자열이고 다른 피연산자는 숫자이며, EEA 규칙 2.2에 따라 ''가 숫자로 변환 됨)

2. 0 == 0 (피연산자는 동일한 유형이며 EEA 규칙 1을 사용하여 동일성을 일치성 평가로 변환)

3. 0 === 0 (연산자는 동일한 유형이고 동일한 값을 가지므로 IEA 규칙 6에 따라 일치합니다)

4. 결과값은 true임

 

예제 3

null == 0 // false

1. null == 0 (null은 null 타입의 프리미티브 타입이고 0은 숫자입니다. EEA 규칙 3 적용)

2. 결과값은 false 임

 

예제 4

null == undefined // true

1. null == undefined (EEA 규칙 2.1에 따라 피연산자가 동일 함)

2. 결과값은 true 임

 

예제 5

NaN == NaN // false

1. NaN == NaN (두 피연산자는 모두 숫자입니다. EEA 규칙 1을 사용하여 동일성을 일치성 평가로 변환)

2. NaN === NaN (규칙 IEA 규칙 4에 따라 피연산자가 완전히 같지 않음)

3. 결과값은 false 임

 

예제 6

[''] == '' // true

1. [''] == '' (['']는 배열이고 ''문자열입니다. EEA 규칙 2.4를 적용하고 OPCA 규칙 2를 사용하여 배열을 프리미티브 타입으로 변환)

2. '' == '' (두 피연산자는 모두 문자열이므로 동등성을 일치성 평가로 변환)

3. '' === '' (두 피연산자는 동일한 유형이고 동일한 값을 갖습니다. IEA 규칙 7을 사용하면 두 피연산자는 일치합니다)

4. 결과값은 true 임

 

예제 7

{} == true // false

1. {} == true (EEA 규칙 2.3을 사용하여 true 피연산자를 1로 변환)

2. {} == 1 (첫 번째 피연산자는 객체이므로 OPCA를 사용하여 프리미티브 타입 즉, 기본 유형으로 변환해야 함)

3. "[object Object]" == 1 (첫 번째 피연산자는 문자열이고 두 번째 피연산자는 숫자이므로 EEA 규칙 2.2를 사용하여 "[object Object]"를 숫자로 변환해야합니다)

4. NaN == 1 (두 피연산자는 모두 숫자이므로 EEA 규칙 1을 사용하여 동등성을 일치성 평가로 변환)

5. NaN === 1 (NaN과 동일한 것이 없다는 IEA 규칙 4에 따라 결과는 거짓 임)

6. 결과값은 false 임

 

 

 

이 글의 모든 예제를 자세히 확인하고 알고리즘을 학습 한 후에도 복잡한 비교를 쉽게 이해하기가 어려울 수 있습니다.

 

솔직히 이 연산자들은 저에게도 오랫동안 블랙 박스였습니다.

 

여기서 약간의 트릭을 알려 드리겠습니다.

 

흥미롭고 어려운 예가 있다면 위의 예제처럼 동등 또는 일치 알고리즘을 기반으로 단계별 계산을 작성하십시오.

 

위에서 보여줬던 10개 이상의 예를 직접 확인하면 향후 문제가 없을 것입니다.

 

그럼 다음 문제도 한번 맞춰 보십시요.

[0] == 0

동등 연산자 ==는 타입 변환을 수행합니다.

 

결과적으로 일부 비교에서 예상치 못한 결과가 발생할 수 있습니다.

 

예를 들어 {} == true는 false입니다 (예 7 참조).

 

대부분의 경우 일치 연산자 ===를 사용하는 것이 더 안전합니다.

 

이상 자바스크립트에서 동등, 일치 연산자에 대해 알아 보았습니다.

 

 

그리드형