태그 보관물: code-quality

code-quality

JavaScript에서 ==를 사용하는 것이 의미가 있습니까? 좋은 것은 당신이 기대하는 방식으로 작동합니다. 두

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

: 자바 스크립트는이 개 평등 사업자의 세트를 가지고 ===!==, 그들의 사악한 쌍둥이 ==!=. 좋은 것은 당신이 기대하는 방식으로 작동합니다. 두 피연산자가 동일한 유형이고 동일한 값을 갖는 경우, ===생성 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===연산자로 생성 됩니다 .

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



답변

나는 논쟁을 할 것이다 ==

당신이 인용 한 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 

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

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


답변

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가이 를 위해 특별히 설계된 플래그갖기에 충분 합니다.


답변

풍부하게 설명했듯이 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”가;


답변

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

결론

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


답변

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

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).


답변

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

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

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


답변

나는이 늦은 대답을 알고 있지만, 일부 수에 대한 혼란이있을 것 같습니다 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 : 허위는 훌륭한 개념입니다. 평등으로 확장해서는 안됩니다.