[javascript] 이것은 !! JavaScript가 아닌 연산자입니까?

인식하지 못하는 연산자를 사용하는 것으로 보이는 일부 코드는 다음과 같이 두 개의 느낌표 형태로 나타납니다 !!. 누군가이 연산자가 무엇을하는지 말해 줄 수 있습니까?

내가 본 상황은

this.vertical = vertical !== undefined ? !!vertical : this.vertical;



답변

로 변환 Object합니다 boolean. 은 (예를 들어 falsey 있었다면 0, null, undefined, 등)이있을 것이다 false, 그렇지 않으면 true.

!oObject  // inverted boolean
!!oObject // non inverted boolean so true boolean representation

따라서 !!연산자는 아닙니다 !. 연산자는 두 번입니다.

실제 예제 “Test IE version”:

const isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);
console.log(isIE8); // returns true or false 

당신이 ⇒

console.log(navigator.userAgent.match(/MSIE 8.0/));
// returns either an Array or null  

하지만 ⇒

console.log(!!navigator.userAgent.match(/MSIE 8.0/));
// returns either true or false


답변

형식 변환을 수행하는 끔찍한 방법입니다.

!이다 NOT . 그래서이 !true있다 false, 그리고 !false이다 true. !0이다 true, 그리고 !1이다 false.

따라서 값을 부울로 변환 한 다음 뒤집은 다음 다시 뒤집습니다.

// Maximum Obscurity:
val.enabled = !!userId;

// Partial Obscurity:
val.enabled = (userId != 0) ? true : false;

// And finally, much easier to understand:
val.enabled = (userId != 0);


답변

!!expr식 의 진실성 에 따라 부울 값 ( true또는 false)을 반환합니다 . 부울이 아닌 유형에 사용될 때 더 의미가 있습니다. 다음 예, 특히 세 번째 예 이상을 고려하십시오.

          !!false === false
           !!true === true

              !!0 === false
!!parseInt("foo") === false // NaN is falsy
              !!1 === true
             !!-1 === true  // -1 is truthy

             !!"" === false // empty string is falsy
          !!"foo" === true  // non-empty string is truthy
        !!"false" === true  // ...even if it contains a falsy value

     !!window.foo === false // undefined is falsy
           !!null === false // null is falsy

             !!{} === true  // an (empty) object is truthy
             !![] === true  // an (empty) array is truthy; PHP programmers beware!


답변

차를 끓이십시오 :

!!연산자가 아닙니다. !논리적 “not”연산자 인 이중 사용입니다 .


이론에 의하면:

! 값이 아닌 “진실”을 결정합니다.

  • 진실은 즉 false하지 않습니다 true(이유 그 !false결과 true)

  • 진실은 즉 true하지 않습니다 false(이유 그 !true결과 false)


!!값이 아닌 것에 대한 “진실”을 결정합니다 .

  • 진실은 즉 true하지 하지 true (의 그 이유는 !!true결과 true)

  • 진실은 즉 false하지 하지 false (의 그 이유는 !!false결과 false)


우리가 비교에서 결정하고자하는 것은 참조 값에 대한 “진실” 입니다. 것은 참조 자체 입니다. 값이 false(또는 잘못된) 것으로 예상되거나 값이 typeof가 아닌 것으로 예상 하더라도 값에 대한 진실을 알고 싶어하는 유스 케이스가 있습니다 boolean.


실제로:

동적 타이핑 (일명 “덕 타이핑”)을 통해 기능 기능 (이 경우 플랫폼 호환성)을 감지하는 간결한 기능을 고려하십시오 . true사용자 브라우저가 HTML5 <audio>요소를 지원하는 경우 반환하는 함수를 작성하려고 하지만 <audio>정의되지 않은 경우 함수가 오류를 발생시키지 않도록합니다 . try ... catch가능한 오류를 처리하는 데 사용하고 싶지 않습니다 (매우 심각하기 때문에). 또한 기능에 대한 진실을 일관되게 밝히지 않는 함수 내부에서 검사를 사용하고 싶지 않습니다 (예 :document.createElement('audio')<audio> HTML5 <audio>가 지원되지 않는 경우에도 여전히 요소를 생성합니다 ).


세 가지 접근 방식은 다음과 같습니다.

// this won't tell us anything about HTML5 `<audio>` as a feature
var foo = function(tag, atr) { return document.createElement(tag)[atr]; }

// this won't return true if the feature is detected (although it works just fine)
var bar = function(tag, atr) { return !document.createElement(tag)[atr]; }

// this is the concise, feature-detecting solution we want
var baz = function(tag, atr) { return !!document.createElement(tag)[atr]; }

foo('audio', 'preload'); // returns "auto"
bar('audio', 'preload'); // returns false
baz('audio', 'preload'); // returns true

각 함수는 a <tag>와 a에 대한 인수를 허용합니다 .attribute 하지만 비교가 결정한 내용에 따라 서로 다른 값을 반환합니다.

그러나 더 많은 것이 있습니다!

여러분 중 일부는이 특정 예 에서 문제의 객체에 속성 있는지 확인 하는 약간 더 성능이 좋은 방법을 사용하여 속성을 간단히 확인할 수 있음을 알았습니다 . 이를 수행하는 두 가지 방법이 있습니다.

// the native `hasOwnProperty` method
var qux = function(tag, atr) { return document.createElement(tag).hasOwnProperty(atr); }

// the `in` operator
var quux = function(tag, atr) { return atr in document.createElement(tag); }

qux('audio', 'preload');  // returns true
quux('audio', 'preload'); // returns true

우리는 …

그러나 이러한 상황이 드물기는하지만 true부울이 아닌 정의되지 않은 값에서 가져 오는 가장 간결하고 성능이 좋으며 가장 선호되는 방법 이 실제로 사용 되는 몇 가지 시나리오가있을 수 있습니다 !!. 잘하면 이것은 말도 안되게 정리합니다.


답변

!!오른쪽의 값을 동등한 부울 값으로 변환합니다. (가난한 사람의 “유형 캐스팅”방식을 생각하십시오). 이것의 목적은 코드 상관하지 않는 독자에게 전달하기 위해 일반적으로 어떤 값이 변수이지만, 그것의 어떤 “진리”값 입니다.


답변

!!foo단항 not 연산자를 두 번 적용하고 단항 더하기 +foo를 사용 하여 숫자로 캐스트하고 빈 문자열을 연결하는 것과 유사한 부울 유형으로 캐스트하는 데 사용됩니다.''+foo 을 로 캐스트하는 .

이러한 해킹 대신 기본 유형에 해당하는 생성자 함수 사용하여 ( 사용 하지 않고new ) 명시 적으로 값을 캐스트 할 수 있습니다.

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo


답변

작업의 절반을 수행하는 많은 답변. 예, !!X“X의 진실성 [부울로 표현됨]이라고 읽을 수 있습니다. 그러나 !!실제로 말해서 단일 변수가 진실인지 거짓인지 알아내는 데 중요하지 않습니다. !!myVar === true그냥 동일합니다 myVar. 비교!!X“실제”부울과 하는 것은 실제로 유용하지 않습니다.

당신이 얻는 !!것은 서로에 대해 여러 변수의 진실성을 확인하는 능력입니다 것은 반복 가능하고 표준화 된 (그리고 JSLint 친화적 인) 방식 입니다.

단순히 캐스팅 🙁

그건…

  • 0 === false입니다 false.
  • !!0 === false입니다 true.

위의 내용은 그렇게 유용하지 않습니다. if (!0)와 동일한 결과를 제공합니다 if (!!0 === false). 변수를 부울로 캐스트 한 다음 “참”부울과 비교하는 좋은 사례는 생각할 수 없습니다.

JSLint의 지시에 따라 “== 및! =”를 참조하십시오 (참고 : Crockford가 약간의 사이트를 이동하고 있습니다. 해당 링크는 어느 시점에서 죽기 쉽습니다).

== 및! = 연산자는 비교하기 전에 강제 변환을 수행합니다. ‘\ t \ r \ n’== 0이 참이기 때문에 이것은 나쁩니다. 유형 오류를 마스크 할 수 있습니다. JSLint는 ==가 올바르게 사용되고 있는지 확실하게 확인할 수 없으므로 == 및! =를 전혀 사용하지 않고 항상보다 안정적인 === 및! == 연산자를 사용하는 것이 가장 좋습니다.

값이 진실이거나 허위임을 신경 쓰는 경우 짧은 형식을 사용하십시오. 대신에
(foo != 0)

그냥 말해
(foo)

대신에
(foo == 0)

말하다
(!foo)

참고 일부 있다는 것을 직관적 경우 부울이 숫자로 캐스팅 될 것입니다 ( true에 캐스팅 1false0숫자로 부울을 비교할 때). 이 경우 !!정신적으로 유용 할 수 있습니다. 다시, 이것은 부울이 아닌 것을 하드 타입의 부울과 비교하는 경우입니다. if (-1)여전히 여기가는 길입니다.

╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
               Original                    Equivalent       Result   
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (-1 == true) console.log("spam")    if (-1 == 1)       undefined 
 if (-1 == false) console.log("spam")   if (-1 == 0)       undefined 
   Order doesn't matter...                                           
 if (true == -1) console.log("spam")    if (1 == -1)       undefined 
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (!!-1 == true) console.log("spam")  if (true == true)  spam       better
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
 if (-1) console.log("spam")            if (truthy)        spam       still best
╚═══════════════════════════════════════╩═══════════════════╩═══════════╝

그리고 엔진에 따라 상황이 훨씬 더 어려워집니다. 예를 들어 WScript가 상을 수상합니다.

function test()
{
    return (1 === 1);
}
WScript.echo(test());

역사적인 Windows jive 때문에 메시지 상자에 -1이 출력됩니다! cmd.exe 프롬프트에서 시도해보십시오! 그러나 WScript.echo(-1 == test())여전히 0 또는 WScript를 제공합니다 false. 멀리 봐 끔찍 해요

진실성 비교 🙂

그러나 두 가지 가치가 있다면 동일한 진실성 / 거짓 성을 확인해야합니까?

우리가있는 척 myVar1 = 0;하고 myVar2 = undefined;.

  • myVar1 === myVar2이다 0 === undefined명백하게 거짓입니다.
  • !!myVar1 === !!myVar2이다 !!0 === !!undefined와 사실이다! 같은 진실성! (이 경우, 둘 다 “거짓의 진실성을가집니다”.

따라서 실제로 “부울 캐스트 변수”를 사용해야하는 유일한 장소는 두 변수가 동일한 진실성을 갖는지 확인하는 상황이있는 것입니다 . 즉, 사용 !!두 바르가 있는지 확인해야하는 경우 truthy 또는 둘 모두 falsy 모두 , (또는하지 않음), 동등의 (여부) truthiness .

나는 그 미손에 대한 유인되지 않은 훌륭한 유스 케이스를 생각할 수 없다. 양식에 “연결된”필드가 있습니까?

if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
    errorObjects.spouse = "Please either enter a valid name AND age "
        + "for your spouse or leave all spouse fields blank.";
}

따라서 배우자 이름과 나이에 대해 모두 진실 하거나 허위 인 경우 계속할 수 있습니다. 그렇지 않으면 가치가있는 필드 (또는 매우 이른 결혼 생활)가 하나 있고 errorObjects컬렉션 에 추가 오류가 발생해야합니다 .


2017 년 10 월 24 일, 2 월 19 일 편집 :

명시 적 부울 값이 필요한 타사 라이브러리

흥미로운 사례 !!가 있습니다 … 타사 라이브러리가 명시적인 부울 값을 기대할 때 유용 할 수 있습니다.

예를 들어, JSX (React)의 False는 단순한 허위로 유발되지 않는 특별한 의미 를 갖습니다. JSX에서 다음과 같은 것을 반환하려고 시도하면 int in messageCount

{messageCount && <div>You have messages!</div>}

… 메시지가 없을 0때 React가 a를 렌더링하는 것을보고 놀랄 수도 있습니다 . JSX가 렌더링되지 않도록하려면 명시 적으로 false를 반환해야합니다. 위의 명령문은 0JSX를 정상적으로 렌더링하는을 반환 합니다. 그것은 당신이하지 않았다 Count: {messageCount && <div>Get your count to zero!</div>}(또는 덜 고안된 것을) 말할 수 없습니다 .

  • 한 수정 강제 변환 방방, 관련 0으로 !!0인을 false:
    {!!messageCount && <div>You have messages!</div>}

  • JSX의 문서는 더 명확하고 자체 주석 코드를 작성하며 비교를 사용하여 부울로 강제합니다.
    {messageCount > 0 && <div>You have messages!</div>}

  • 나는 삼항으로 자신을 조작하는 것이 더 편합니다.
    {messageCount ? <div>You have messages!</div> : false}

Typescript와 같은 거래 : 불리언을 반환하는 함수가 있거나 불리언 변수에 값을 할당하는 경우, 일반적으로 불리언 y 값을 반환 / 할당 할 수 없습니다. 강력하게 형식화 된 부울이어야합니다. 이것은 iff myObject가 강력하게 입력 되고 return !myObject;부울을 반환하는 함수 에는 작동하지만 return myObject;그렇지 않은 것을 의미합니다. return !!myObjectTypescript의 기대치와 일치 해야합니다 .

Typescript의 예외? 경우 myObject을했다 any, 당신은 다시 자바 스크립트의 서부에있어,없이 반환 할 수 있습니다 !!당신의 반환 형식이 부울 경우에도.

있다는 사실을 숙지 이러한 JSX & 타이프 라이터 규칙입니다 자바 스크립트가 아니라 고유의 것들 .

그러나 0렌더링 된 JSX에 이상한 것이 있으면 허위 관리를 느슨하게 생각하십시오.