JavaScript에서 ==를 사용하는 것이 의미가 있습니까?


276

에서 자바 스크립트, 좋은 부품 , 더글러스 크록 포드는 썼다 :

: 자바 스크립트는이 개 평등 사업자의 세트를 가지고 ===!==, 그들의 사악한 쌍둥이 ==!=. 좋은 것은 당신이 기대하는 방식으로 작동합니다. 두 피연산자가 동일한 유형이고 동일한 값을 갖는 경우, ===생성 true하고 !==생성합니다 false. 피연산자가 같은 유형일 때 사악한 쌍둥이가 옳은 일을하지만 다른 유형일 경우 값을 강요하려고합니다. 그들이하는 규칙은 복잡하고 기억에 남습니다. 흥미로운 사례는 다음과 같습니다.

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

전이성의 결여가 놀랍습니다. 나의 충고는 결코 사악한 쌍둥이를 사용하지 않는 것입니다. 대신, 항상 사용 ===하고 !==. 방금 표시된 모든 비교 false===연산자로 생성 됩니다 .

이 명백한 관찰을 감안할 때, 사용 ==이 실제로 적절한 시간이 있습니까?


11
그것은 의미가 많은 장소에서. 같은 유형의 두 가지를 비교한다는 것이 명백 할 때마다 (이것은 내 경험에서 많이 발생합니다) == vs === 그냥 선호도에 도달합니다. 다른 경우에는 실제로 추상적 비교를 원합니다 (예 : 답변에서 언급 한 경우). 적절한 지 여부는 주어진 프로젝트의 규칙에 따라 다릅니다.
Hey

4
내 경험상 "많은 장소"에 관해서는 그것이 중요하지 않은 경우보다 중요합니다. 경험이 다를 수 있습니다. 다른 종류의 프로젝트에 대한 경험이있을 수도 있습니다. ==기본적으로 사용 하는 프로젝트를 볼 때 눈에 띄고 ===중요한 일이 진행되고 있음을 알려줍니다.
Hey

4
JavaScript가 유형 강제로 충분하지 않다고 생각합니다. BS 언어 와 마찬가지로 더 많은 유형의 강제 옵션이 있어야 합니다.
Mark Booth

5
==를 사용하는 한 곳은 드롭 다운 ID (항상 char)를 모델 ID (일반적으로 int)와 비교할 때입니다.
Scottie

12
@DevSolar 웹 개발은 15 개 플랫폼 각각에 대한 고유 앱 제작 및 하나의 플랫폼이있는 각 플랫폼의 독점 App Store에 대한 인증을 다루고 싶지 않을 때 적합합니다.
Damian Yerrick

답변:


232

나는 논쟁을 할 것이다 ==

당신이 인용 한 Douglas Crockford는 그의 많은 유용한 의견으로 알려져 있습니다. 이 특정 경우에 Crockford와 함께하는 동안 유일한 의견 은 아닙니다 . 언어 제작자 Brendan Eich와 같은 큰 문제를 보지 못한 사람들도 있습니다 ==. 논쟁은 다음과 같이 조금 진행됩니다.

JavaScript는 행동 유형 * 언어입니다. 사물은 실제 유형이 아니라 할 수있는 것에 따라 처리됩니다. 그렇기 때문에 .mapNodeList 또는 jQuery 선택 세트에서 배열의 메소드를 호출 할 수 있습니다 . 3 - "5""5"는 숫자처럼 행동 할 수 있기 때문에 당신이 할 수 있고 의미있는 것을 되 찾을 수있는 이유이기도합니다 .

==동등성 을 수행하면 변수 유형이 아닌 변수 의 내용 을 비교 하게 됩니다 . 유용한 경우는 다음과 같습니다.

  • 사용자로부터 숫자 읽기-DOM에서.value 입력 요소를 읽 습니까? 문제 없어요! 당신은 그것을 캐스팅하거나 그 유형에 대해 걱정할 필요가 없습니다-당신은 ==즉시 숫자에 도달하고 의미있는 것을 얻을 수 있습니다.
  • 선언 된 변수의 "존재"를 확인해야합니까? - == null행동 적 null으로 거기에 아무것도없고, 정의되지 않은 것도 거기에 아무것도 없기 때문에 가능합니다.
  • 사용자로부터 의미있는 입력을 받았는지 확인해야합니까? - ==인수로 입력이 거짓인지 확인하면 사용자가 아무것도 입력하지 않았거나 공백을 입력 한 경우를 처리합니다. 아마도 필요한 것입니다.

Crockford의 예를보고 행동 적으로 설명해 보겠습니다.

'' == '0'           // got input from user vs. didn't get input - so false
0 == ''             // number representing empty and string representing empty - so true
0 == '0'            // these both behave as the number 0 when added to numbers - so true    
false == 'false'    // false vs got input from user which is truthy - so false
false == '0'        // both can substitute for 0 as numbers - so again true

false == undefined  // having nothing is not the same as having a false value - so false
false == null       // having empty is not the same as having a false value - so false
null == undefined   // both don't represent a value - so true

' \t\r\n ' == 0     // didn't get meaningful input from user vs falsey number - true 

기본적으로, ==프리미티브 방법에 따라 작동하도록 설계되었습니다 행동 들이 무엇을 기반으로하지 않는 자바 스크립트에 있습니다 . 개인적으로이 견해에 동의하지는 않지만, 특히 언어 전체의 행동을 기반으로 유형을 치료하는 패러다임을 취한다면이를 수행하는 데 장점이 있습니다.

* 어떤 사람들은 좀 더 일반적인 이름 구조적 타이핑을 선호 할 수도 있지만 차이점이 있습니다. 여기서 차이점을 논의하는 데 관심이 없습니다.


8
이것은 훌륭한 답변이며 세 가지 'for =='사용 사례를 모두 사용합니다. # 1 & # 3이 특히 유용합니다.
Chris Cirefice

224
문제 ==는 그 비교가 유용 하지 않다는 것이 아니라 규칙 을 기억 하는 것이 불가능 하므로 실수를 저지르는 것이 거의 보장된다는 것입니다. 예를 들어 : "사용자로부터 의미있는 입력을 받았는지 확인해야합니까?"이지만 '0'은 의미있는 입력이며 '0'==false사실입니다. 만약 당신이 ===그것을 사용했다면 당신은 그것에 대해 명시 적으로 생각해야했을 것입니다. 그리고 당신은 실수를하지 않았을 것입니다.
Timmmm

44
"규칙은 기억하기 불가능하다"<== 이것은 자바 스크립트에서 "의미있는"일을하는 것을 무서워하는 것입니다. (그리고 기본적인
계산법

9
3 - "5"예제는 독자적으로 좋은 점을 제기합니다. ===비교를 위해 독점적으로 사용하더라도 변수가 Javascript에서 작동하는 방식입니다. 완전히 탈출 할 방법이 없습니다.
Jarett Millard

23
@Timmmm 여기서 악마의 옹호자를하고 있습니다. 나는 ==내 자신의 코드에서 사용하지 않고 안티 패턴을 발견하고 추상 평등 알고리즘을 기억하기 어렵다는 것에 완전히 동의합니다. 내가 여기서하는 일은 사람들이 주장하는 것입니다.
Benjamin Gruenbaum

95

jQuery가 구문을 사용한다는 것이 밝혀졌습니다.

if (someObj == null) {
  // do something
}

등가 코드의 줄임말로 광범위하게 :

if ((someObj === undefined) || (someObj === null))  {
  // do something
}

이는 ECMAScript 언어 사양 § 11.9.3, 추상 평등 비교 알고리즘의 결과로 ,

1.  If Type(x) is the same as Type(y), then  
    a.  If Type(x) is Undefined, return true.  
    b.  If Type(x) is Null, return true.

2.  If x is null and y is undefined, return true.
3.  If x is undefined and y is null, return true.

이 특정 기술은 JSHint가이 를 위해 특별히 설계된 플래그갖기에 충분 합니다.


10
나는이 :) 대답하고 싶어 자신의 질문에 대답 없음 박람회는 == null or undefined내가 사용하지 않는 유일한 장소입니다 ===또는!==
pllee

26
공정한 jQuery는 모델 코드베이스가 아닙니다. jQuery 소스를 여러 번 읽은 것은 중첩 된 삼항, 불분명 한 비트, 중첩 및 실제 코드에서 피해야 할 것들이 많은 가장 좋아하는 코드베이스 중 하나입니다. 그래도 내 말을하지 마십시오 -github.com/jquery/jquery/tree/master/src를 읽고 jQuery 클론 인 Zepto 와 비교하십시오 : github.com/madrobby/zepto/tree/master/src
Benjamin Gruenbaum

4
또한 Zepto는 기본적으로 필요한 것으로 보이며 필요한 경우 ==에만 사용 ===합니다. github.com/madrobby/zepto/blob/master/src/event.js
Hey

2
@Hey 공정한 Zepto는 모델 코드베이스가 아닙니다 __proto__. 모바일 웹 사이트가 중단되는 것을 피하기 위해 언어 사양을 거의 사용하지 않고 강제 로 사용하는 것으로 유명합니다 .
Benjamin Gruenbaum

2
@BenjaminGruenbaum은 코드베이스의 품질에 대한 판단이 아니며 다른 프로젝트가 다른 규칙을 따릅니다.
Hey

15

풍부하게 설명했듯이 null또는 값을 확인하는 undefined것이 하나입니다.

또 다른 점이 있습니다 ==.

다음과 >=같이 비교를 정의 할 수 있습니다 (사람들은 일반적으로 시작 >하지만 더 우아합니다).

  • a > b <=> a >= b && !(b >= a)
  • a == b <=> a >= b && b >= a
  • a < b그리고 a <= b독자에게 연습으로 남아 있습니다.

아시다시피, JavaScript "3" >= 3"3" <= 3을 통해 얻을 수 3 == "3"있습니다. 문자열을 구문 분석하여 문자열과 숫자를 비교하는 것이 끔찍한 아이디어라는 점을 지적 할 수 있습니다. 그러나 그것이 작동하는 방식이다 주어진 ==절대적으로 그 관계 연산자를 구현하는 올바른 방법.

정말 좋은 점은 ==다른 모든 관계와 일관성이 있다는 것입니다. 이것을 쓰면 다르게 말하면 :

function compare(a, b) {
  if (a > b) return 1;
  if (a < b) return -1;
  return 0;
}

==이미 암시 적으로 사용 하고 있습니다.

다음과 관련이 있습니다 : 숫자와 문자열 비교를 구현하는 것이 나쁜 선택입니까? 격리 된 상태에서 보면 어리석은 일인 것 같습니다. 그러나 JavaScript 및 DOM의 다른 부분과 관련하여 다음과 같은 점을 고려하면 비교적 실용적입니다.

  • 속성은 항상 문자열입니다
  • 키는 항상 문자열입니다 (사용 사례는 Objectint에서 값으로 스파 스 맵을 갖기 위해 사용 합니다)
  • 사용자 입력 및 양식 제어 값은 항상 문자열입니다 (소스가 일치하더라도 input[type=number])

여러 가지 이유로 문자열은 필요할 때 숫자처럼 동작하도록하는 것이 합리적입니다. 그리고 문자열 비교와 문자열 연결에 다른 연산자가 있다고 가정하면 (예 : 연결 ::및 비교 방법 (대 / 소문자 구분에 대한 모든 종류의 매개 변수를 사용할 수있는 경우)) 실제로 이것은 엉망이되지 않습니다. 그러나이 연산자 오버로딩은 아마도 "JavaScript"의 "Java"가;


4
공평하다는 >=것은 실제로 전이되지 않습니다. JS에서 또는 (예 :) 어느 a > b것도 가능하지 않습니다 . a < bb == aNaN
Benjamin Gruenbaum

8
@ BenjaminGruenbaum : 그것은 보유하지 않기 +때문에 실제로는 정식 이 아니라고 말하는 것과 같습니다 NaN + 5 == NaN + 5. 요점은 일관되게 >=작동하는 숫자 값으로 작동 한다는 것 ==입니다. "숫자가 아님"은 본질적으로 숫자가 아니라;)
back2dos

4
의 나쁜 행동은의 나쁜 행동과 ==일치합니다 >=. 대단한, 지금 나는 있었으면 좋겠다 >==...
Eldritch Conundrum

2
@ EldritchConundrum : 설명하려고 시도했지만 동작은 >=나머지 언어 / 표준 API와 다소 일치합니다. 전체적으로, JavaScript는 기발한 부분의 합보다 많을 수 있습니다. 당신이 원하는 경우 >==, 당신은 또한 엄격한 원 +하십니까? 실제로, 이러한 결정 중 많은 부분이 많은 것을 훨씬 쉽게 만듭니다. 그래서 나는 그들을 가난하다고 판단하기 위해 서두르지 않을 것입니다.
back2dos

2
@EldritchConundrum : 다시 : 관계 연산자는 하나의 피연산자가 실제로 문자열 일 수있는 숫자 값을 비교하기위한 것입니다. >=의미있는 피연산자 유형의 경우 ==똑같이 의미가 있습니다. 아무도 당신 [[]]과 비교해야한다고 말하지 않습니다 false. C와 같은 언어에서이 수준의 넌센스 결과는 정의되지 않은 동작입니다. 같은 방식으로 취급하십시오.하지 마십시오. 그리고 당신은 괜찮을거야. 또한 마술 규칙을 기억할 필요가 없습니다. 그리고 실제로는 다소 직설적입니다.
back2dos

8

전문 수학자로서 Javscript의 동일 연산자 == ( "추상 비교", "느슨한 평등" 이라고도 )에서 엔티티 사이에 등가 관계 를 구축하려는 시도가 있습니다 . 여기에는 반사 , 대칭전이가 포함 됩니다. 불행히도이 세 가지 기본 속성 중 두 개는 실패합니다.

==재귀 하지 않습니다 :

A == A 예를 들어 거짓 일 수 있습니다.

NaN == NaN // false

==전이 되지 않습니다 :

A == BB == C함께 의미하지는 않습니다 A == C, 예를 들어,

'1' == 1 // true
1 == '01' // true
'1' == '01' // false

대칭 속성 만 유지됩니다.

A == BB == A어떤 위반이라도 생각할 수 없으며 심각한 반란을 초래할 수 있음을 암시합니다 .)

동등성 관계가 중요한 이유

그것이 가장 중요하고 널리 알려진 관계 유형이기 때문에 수많은 예제와 응용 프로그램에서 지원됩니다. 가장 중요한 응용은 엔티티를 동등성 클래스 로 분해 하는 것인데, 이는 그 자체가 관계를 이해하는 매우 편리하고 직관적 인 방법입니다. 그리고 동등성이 아닌 것은 동등성 클래스의 부족으로 이어지고, 이는 잘 알려진 직관적 성과 불필요한 복잡성의 부족으로 이어진다.

==비동 등 관계 를 작성하는 것이 왜 그렇게 끔찍한 생각 입니까?

문자 그대로 유사성, 평등, 합동, 동 형사상, 정체성 등의 흥미로운 관계가 동등하므로 이는 우리의 친숙 함과 직관을 깨뜨리기 때문입니다.

타입 변환

JavaScript 는 직관적 인 동등성에 의존하는 대신 유형 변환을 도입합니다.

항등 연산자는 피연산자가 동일한 유형이 아닌 경우 피연산자를 변환 한 다음 엄격한 비교를 적용합니다.

그러나 유형 변환은 어떻게 정의됩니까? 수많은 예외를 포함한 복잡한 규칙 집합을 통해?

동등성 관계 구축 시도

부울. 명확 true하고 false동일하지 않으며 다른 클래스에 있어야합니다.

번호. 운좋게도, 숫자의 평등은 이미 잘 정의되어 있으며, 두 개의 다른 숫자는 같은 동등 클래스에 속하지 않습니다. 수학에서 그렇습니다. 자바 스크립트에서 숫자의 개념이되어 다소 변형 더 이국적인의 존재를 통해 -0, Infinity그리고 -Infinity. 우리의 수학적 직관 것을 지시 0하고 -0(사실은 동일한 클래스에 있어야 -0 === 0입니다 true) 무한대의 각각 별도의 클래스 반면,.

숫자와 부울. 숫자 클래스가 주어지면 부울을 어디에 넣습니까? false유사하게 0, 반면 true유사하게 1하지만, 다른 수 :

true == 1 // true
true == 2 // false

여기에 true합칠 논리 가 1있습니까? 물론 1그렇습니다 -1. 개인적으로로 변환 true할 이유가 없습니다 1.

그리고 그것은 더욱 악화됩니다.

true + 2 // 3
true - 1 // 0

그래서 true참으로 변환되는 1모든 숫자들! 논리적입니까? 직관적입니까? 답은 운동으로 남습니다.)

그러나 이것에 대해서는 :

1 && true // true
2 && true // true

유일한 부울 x을 가진 x && true존재가 true있다 x = true. 어느 모두 증명 12(와 이외의 다른 번호 0)로 변환 true! 그것이 보여주는 것은 우리의 전환이 또 다른 중요한 속성 인 실패라는 입니다. 두 개의 다른 엔터티가 동일한 것으로 변환 될 수 있음을 의미합니다. 그 자체만으로는 큰 문제 일 필요는 없습니다. 우리가이 변환을 사용하여 우리가 부르고 싶은 것의 "동일성"또는 "느슨한 평등"의 관계를 설명 할 때 큰 문제가 발생합니다. 그러나 한 가지 분명한 것은 동등성 관계가 아니며 동등성 클래스를 통해 직관적으로 설명되지 않는 것입니다.

그러나 우리는 더 잘할 수 있습니까?

적어도 수학적으로는-물론 그렇습니다! 논리 값 및 숫자 사이에 간단한 동치 관계는 단지로 구성 할 수 false0같은 클래스에있는. 따라서 false == 0사소한 느슨한 평등이 될 것입니다.

문자열은 어떻습니까?

시작과 끝의 공백에서 문자열을 잘라내어 숫자로 변환 할 수 있으며 앞에있는 0을 무시할 수도 있습니다.

'   000 ' == 0 // true
'   0010 ' == 10 // true

따라서 문자열에 대한 간단한 규칙을 얻습니다. 공백과 0을 트리밍합니다. 우리는 숫자 또는 빈 문자열을 얻습니다.이 경우 해당 숫자 또는 0으로 변환됩니다. 또는 우리는 숫자를 얻지 못합니다.이 경우 우리는 변환하지 않으므로 새로운 관계를 얻지 못합니다.

이런 식으로 우리는 실제로 전체 부울, 숫자 및 문자열 집합에서 완벽한 동등 관계를 얻을 수 있습니다! 그것을 제외하고 ... JavaScript 디자이너는 분명히 다른 의견을 가지고 있습니다 :

' ' == '' // false

따라서 둘 다로 변환되는 두 줄 0은 갑자기 비슷하지 않습니다! 왜 또는 왜? 규칙에 따르면, 문자열은 엄격하게 같을 때 정확하게 동일하지 않습니다! 이 규칙은 우리가 보는 것처럼 전이성을 깨뜨릴뿐만 아니라 중복입니다! 다른 연산자 ==를 다른 연산자 와 엄격하게 동일하게 만들기위한 요점은 무엇입니까 ===?

결론

느슨한 평등 연산자 ==는 기본 수학 법칙을 준수하는 경우 매우 유용했을 수 있습니다. 그러나 슬프게도 그렇지 않아 유용성이 떨어집니다.


무엇에 대해 NaN? 또한 문자열과 비교하기 위해 특정 숫자 형식을 적용하지 않으면 직관적이지 않은 문자열 비교 또는 비 일시적 결과가 발생해야합니다.
솔로몬 유코

@SolomonUcko NaN는 나쁜 시민으로 행동합니다 :-). 직관성 여부에 관계없이 동등성을 비교하기 위해 전이성을 유지해야합니다.
Dmitri Zaitsev

7

예, 를 숫자 값과 비교할 때 유스 케이스를 살펴 보았습니다 .

for (var key in obj) {
    var some_number = foo(key, obj[key]);  // or whatever -- this is just an example
    if (key == some_number) {
        blah();
    }
}

나는 key == some_numberas Number(key) === some_number또는 as 보다는 비교를 수행하는 것이 훨씬 더 자연 스럽다고 생각합니다 key === String(some_number).


3

나는 오늘 꽤 유용한 응용 프로그램을 보았습니다. 01일반 정수 와 같이 채워진 숫자를 비교 하려면 정상적으로 ==작동합니다. 예를 들면 다음과 같습니다.

'01' == 1 // true
'02' == 1 // false

0을 제거하고 정수로 변환하는 것을 저장합니다.


4
이 작업을 수행하는 '올바른'방법은 '04'-0 === 4, 또는 아마도parseInt('04', 10) === 4
아마도

나는 당신이 이것을 할 수 있다는 것을 몰랐습니다.
Jon Snow

7
나는 그것을 많이 얻는다.
Jon Snow

1
@ratbum 또는+'01' === 1
Eric Lagergren

1
'011' == 011 // false엄격하지 않은 모드에서는 엄격하고 엄격 모드에서는 SyntaxError입니다. :)
Brian S

3

나는이 늦은 대답을 알고 있지만, 일부 수에 대한 혼란이있을 것 같습니다 nullundefined만드는 것입니다 IMHO, ==악, 더 때문에 충분히 나쁜 이행 성의 부족, 그. 치다:

p1.supervisor = 'Alice';
p2.supervisor = 'None';
p3.supervisor = null;
p4.supervisor = undefined;

이것들은 무엇을 의미합니까?

  • p1 이름이 "Alice"인 감독자가 있습니다.
  • p2 이름이 '없음'인 관리자가 있습니다.
  • p3명백히 명백하게 감독자가 없습니다 .
  • p4관리자가있을 수도 있고 없을 수도 있습니다. 우리는 알지 못합니다. 상관하지 않습니다. 우리의 사업과는 달리 (개인 정보 문제?)

당신이 사용하는 경우 ==는 가미하여 있습니다 nullundefined있는 전적으로 부적절하다. 두 용어는 완전히 다른 것을 의미합니다! 관리자가 누구인지 말하기를 거부했기 때문에 관리자가 없다고 말하는 것!

나는 사이의 차이에 대해 걱정하지 않는다 프로그래머가 이해 null하고 undefined또는 다른 이들 용어를 사용하기로 선택이. 그리고 당신의 세계는 사용하지 않는 경우 nullundefined정확하게하거나 약관에 자신의 해석을 제공하고자하는, 그래서를합니다. 그래도 좋은 생각은 아닙니다.

이제 그런데 나는 아무 문제가 없다 null하고 undefined모두있는 falsy를! 말하는 것은 완벽하다

if (p.supervisor) { ... }

다음 nullundefined생략 할 수있는 관리자를 처리하는 코드를 일으킬 것이다. 우리는 감독자를 모르거나 없기 때문에 정확합니다. 문제 없다. 그러나 두 상황 은 동일하지 않습니다 . 이것이 ==잘못된 이유 입니다. 다시 말하지만, 일이 잘못되어 오리 타이핑 의미로 사용될 수 있으며 이는 동적 언어에 좋습니다. 적절한 JavaScript, Pythonic, Rubyish 등입니다. 그러나 다시 말하지만, 이것들은 동일하지 않습니다.

: 그리고 나 비 이행 성에서 시작하지 않는다 "0x16" == 10, 10 == "10"하지만 "10" == "0x16". 예, JavaScript는 약한 유형입니다. 예, 강제적입니다. 그러나 강제성은 결코 평등에 적용되어서는 안됩니다.

그건 그렇고, Crockford는 강한 의견을 가지고 있습니다. 그러나 당신은 무엇을 알고 있습니까? 그는 여기에 맞습니다!

FWIW 본인 ==은 편리한 상황이 있고, 개인적으로 부딪 쳤음을 이해 합니다! 숫자에 문자열을 입력하고 0과 비교하는 것과 같습니다. 그러나 이것은 해킹입니다. 부정확 한 세계 모델에 대한 절충으로 편리함이 있습니다.

TL; DR : 허위는 훌륭한 개념입니다. 평등으로 확장해서는 안됩니다.


다른 상황을 보여 주셔서 감사합니다 :) 그러나 당신은 빠졌습니다 p5... typeof(p5.supervisor) === typeof(undefined)감독자가 개념으로 존재하지 않는 상황 : D
TheCatWhisperer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.