javascript - 영어 - 자바스크립트 비트연산




이것은 !! JavaScript에서 연산자가 아닌(아닌)? (20)

! 본질적으로 "enable"값을 반대 값으로 typecasting하는 "boolean not"입니다. 두번째 ! 이 값을 뒤집습니다. 따라서, !!enable 은 "not not enable"을 의미하며, !!enable 값을 부울로 제공합니다.

나는 두 개의 느낌표 형태로 인식 할 수없는 연산자를 사용하는 코드를 보았다 !! . 누군가이 연산자가하는 것을 말해 줄 수 있습니까?

내가 이것을 보았던 배경은,

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

C ++의 나머지 부분인데, 사람들이이 부분을 오버라이드 한 것 같습니다. 연산자를 사용하지만 bool 연산자는 사용하지 마십시오.

이 경우 부정 (또는 긍정적) 답변을 얻으려면 먼저! 연산자는 부울을 얻을 수 있지만, 당신이 긍정적 인 경우를 확인하고 싶다면 !!을 사용하십시오 !!.


!! construct는 모든 JavaScript 표현식을 부울로 변환하는 간단한 방법입니다.

예를 들면 !!"he shot me down" === true!!0 === false .


그것은 논리적 NOT 연산자입니다. 두 번입니다. 예를 들어 뭔가를 부울로 변환하는 데 사용됩니다.

true === !!10

false === !!0

그것은 보인다 !! 연산자는 이중 부정을 초래합니다.

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true

그것은 하나의 연산자가 아니라 두 가지입니다. 이것은 다음과 같으며 값을 부울 값으로 변환하는 빠른 방법입니다.

val.enabled = !(!enable);

논리 not 연산자를 두 번 사용하십시오.
의미! true = false
그리고 !! true = true


논리적 인 AND / OR과 결합 된 조건은 부울 값을 반환하지 않지만 마지막 성공 또는 첫 번째 실패는 && 및 첫 번째 성공 또는 마지막 실패 || 조건 체인.

res = (1 && 2); // res is 2
res = (true && alert) // res is function alert()
res = ('foo' || alert) // res is 'foo'

조건을 참 부울 리터럴로 변환하기 위해 우리는 이중 부정을 사용할 수 있습니다 :

res = !!(1 && 2); // res is true
res = !!(true && alert) // res is true
res = !!('foo' || alert) // res is true

변수의 부울 값을 반환합니다.

대신 Boolean 클래스를 사용할 수 있습니다.

(코드 설명을 읽으십시오)

var X = "test"; // X value is "test" as a String value
var booleanX = !!X // booleanX is `true` as a Boolean value beacuse non-empty strings evaluates as `true` in boolean
var whatIsXValueInBoolean = Boolean(X) // whatIsXValueInBoolean is `true` again
console.log(Boolean(X) === !!X) // writes `true`

즉, Boolean(X) = !!X 가 사용 중입니다.

아래에서 코드 스 니펫을 확인하십시오

let a = 0
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a) // writes '0 is NOT true in boolean' value as boolean - So that's true.In boolean 0 means false and 1 means true.
console.log("!!a: ", !!a) // writes 0 value in boolean. 0 means false.
console.log("Boolean(a): ", Boolean(a)) // equals to `!!a`
console.log("\n") // newline

a = 1
console.log("a: ", a)
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes 1 value in boolean
console.log("\n") // newline

a = ""
console.log("a: ", a)
console.log("!a: ", !a) // writes '"" is NOT true in boolean' value as boolean - So that's true.In boolean empty strings, null and undefined values mean false and if there is a string it means true.
console.log("!!a: ", !!a) // writes "" value in boolean
console.log("\n") // newline

a = "test"
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes "test" value in boolean

console.log("Boolean(a) === !!a: ", Boolean(a) === !!a) // writes true


여기에 엄청난 해답이 있습니다. 그러나 지금까지이 기사를 읽으 셨다면, '도와 줘서'도움이되었습니다. Chrome (등)에서 콘솔을 열고 다음을 입력하십시오.

!(!(1))
!(!(0))
!(!('truthy')) 
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

당연히, 이것들은 단지 someThing을 타이핑하는 것과 모두 같습니다만, 괄호를 추가하면 이해하기 쉽습니다.


이중 부울 부정. 종종 값이 정의되지 않았는지 확인하는 데 사용됩니다.


작업의 절반을하는 많은 답변. 예, !!X 는 "X의 진실성 [부울로 표현]"으로 읽을 수 있습니다. 하지만 !! 실제로 하나의 변수가 진실인지 또는 위선인지 여부를 알아 내는데 중요하지 않습니다. !!myVar === true!!myVar === true 와 같습니다. !!X 를 "진짜"부울과 비교하는 것은 실제로 유용하지 않습니다.

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

단순히 주조 :(

그건...

  • 0 === falsefalse 입니다.
  • !!0 === falsetrue 입니다.

위의 것은별로 유용하지 않습니다. if (!0)if (!!0 === false) 와 같은 결과를 제공합니다. 부울로 변수를 캐스팅 한 다음 "true"부울로 비교하는 좋은 경우는 생각할 수 없습니다.

JSLint의 지시 에서 "== and! ="를 참조하십시오 (참고 : Crockford는 약간의 주위로 그의 사이트를 움직이고 있으며, 링크는 어떤 점에서 죽을 것입니다).

== 및! = 연산자는 비교하기 전에 강제 변환을 수행합니다. 이것은 '\ t \ r \ n'== 0이 참이되기 때문에 좋지 않습니다. 이렇게하면 유형 오류가 마스킹 될 수 있습니다. JSLint는 ==가 올바르게 사용되는지 여부를 신뢰할 수 없으므로 == 및! =을 사용하지 말고 항상보다 안정적인 === 및! == 연산자를 사용하는 것이 가장 좋습니다.

가치가 진실이거나 위선이라고 생각하는 경우, 짧은 양식을 사용하십시오. 대신에
(foo != 0)

그냥 말해
(foo)

대신
(foo == 0)

말하다
(!foo)

부울을 숫자와 비교할 때 부울을 숫자로 형변환하는 비 직관적 인 경우 가 있습니다 ( true1 로 캐스트되고 false0 ). 이 경우, !! 정신적으로 유용 할 수 있습니다. 다시 말하지만, 이것은 부울이 아닌 부울을 부울 값과 비교하는 경우입니다. 즉 심각한 오류입니다. if (-1) 이 여전히 여기로가는 길 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; 을 가지고 있다고 myVar1 = 0;myVar2 = undefined; .

  • myVar1 === myVar20 === undefined 으며 분명히 거짓입니다.
  • !!myVar1 === !!myVar2!!0 === !!undefined !!myVar1 === !!myVar2 사실입니다! 똑같은 진리! (이 경우에는 "거짓의 진리가있다").

따라서 "boolean-cast 변수"를 사용해야하는 유일한 곳은 두 변수가 동일한 진실성을 갖는지 확인하는 상황이 있다면 맞습니까? 즉, 사용 !! 두 개의 vars가 진실인지 또는 둘 다 foo (또는 not)인지, 즉 평등 (또는 not true )인지를 알아야 할 필요가 있다면.

그만큼 위대하고 비 의도적 인 사용 사례는 생각할 수 없습니다. 어쩌면 양식에 필드를 "링크"했을 것입니까?

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 일 수정 :

명시 적 부울 값을 예상하는 타사 라이브러리

흥미로운 사건이 있습니다 ... !! 타사 라이브러리가 명시 적 부울 값을 예상 할 때 유용 할 수 있습니다.

예를 들어, JSX (React)의 False는 간단한 오류로 인해 발생하지 않는 특별한 의미 가 있습니다. JSX에서 messageCount 의 int를 기대하면서 다음과 같은 것을 반환하려고 시도한 경우 ...

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

... 0 메시지가있을 때 React render a를 보는 것은 놀랄 것입니다. JSX가 렌더링되지 않게하려면 false를 명시 적으로 반환해야합니다. 위의 명령문은 JSX가 행복하게 렌더링하는 0 반환합니다. Count: {messageCount && <div>Get your count to zero!</div>} (또는 인위적인 것).

  • 한 가지 수정 사항은 00 으로 강제하는 뱅뱅을 포함합니다. 이는 false .
    {!!messageCount && <div>You have messages!</div>}

  • JSX '문서는 당신이 더 노골적이고, 자기 주석 코드를 작성하고, 비교를 사용하여 부울을 만들 것을 제안합니다.
    {messageCount > 0 && <div>You have messages!</div>}

  • 나는 삼자로 자신을 위장하는 것이 더 편하다.
    {messageCount ? <div>You have messages!</div> : false}

이것은 JSX 규칙 이므로 JavaScript 고유의 규칙 이 아닙니다 .

그러나 렌더링 된 JSX에서 이상한 0 발견하면 느슨한 허위 관리를 생각해보십시오.


타입 변환을하는 것은 끔찍하게 모호한 방법입니다.

! 아닙니다 . 그래서 !truefalse 이고, !falsetrue 입니다. !0true 이고 !1false 입니다.

따라서 값을 부울로 변환 한 다음 반전시킨 다음 다시 반전합니다.

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

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

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

!! 값을 오른쪽에있는 해당 부울 값으로 변환합니다. (가난한 사람의 "타입 캐스팅"의 방식을 생각해보십시오.) 그 의도 는 대개 코드가 변수에 어떤 값이 있는지 신경 쓰지 않지만 "진실"값 은 무엇인지 독자에게 알려주는 것입니다.


!!부울 생성자 를 사용하는 것과 비슷 하거나 논리적으로 더 부울 함수 와 유사합니다 .

console.log(Boolean(null)); // Preffered over the Boolean object

console.log(new Boolean(null).valueOf()); // Not recommended for coverting non-boolean values

console.log(!!null); // A hacky way to omit calling the Boolean function, but essentially does the same thing. 


// The context you saw earlier (your example)
var vertical;

function Example(vertical)
{
        this.vertical = vertical !== undefined ? !!vertical : 
        this.vertical; 
        // Let's break it down: If vertical is strictly not undefined, return the boolean value of vertical and set it to this.vertical. If not, don't set a value for this.vertical (just ignore it and set it back to what it was before; in this case, nothing).   

        return this.vertical;
}

console.log( "\n---------------------" )

// vertical is currently undefined

console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

vertical = 12.5; // set vertical to 12.5, a truthy value.
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be true anyway
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

vertical = -0; // set vertical to -0, a falsey value.
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be false either way
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

Falsey 값 자바 스크립트는 강제거짓 , 그리고 truthy 값은 강요사실. Falsey 및 truthy 값은 if명령문 에서 사용될 수 있으며 본질적으로 해당 부울 값에 "맵핑"됩니다. 그러나 대부분 출력 (반환 값)이 다르므로 적절한 부울 값을 자주 사용하지 않아도됩니다.

이것이 캐스팅과 유사 해 보일지 모르지만 현실적으로 이것은 단순한 우연의 일치 일 수 있으며 부울 캐스팅과 같은 의도로 만들어 졌거나 의도적으로 만들어지지 않았습니다. 그럼 그렇게 부르지 마십시오.

왜, 어떻게 작동 하는가?

간결하게하기 위해 다음과 같이 보입니다 ! ( !null ). 반면, null이다 falsey , 그래서 !null사실 . 그런 !true것이 거짓 과 본질적 것 다시 반전 A와이 시간을 제외하고는 이전에 무엇에 적절한 부울 값 (또는 그 반대의 경우도 마찬가지truthy 값 과 같은 {}또는 1).


예제로 돌아 가기

전반적으로, 당신이 보았던 컨텍스트는 단순히 정의 this.vertical되었는지 아닌지에 따라 조정 vertical됩니다. 결과의 불리언 값인 vertical로 설정됩니다. 그렇지 않으면 변경되지 않습니다. 즉, vertical정의 된 경우 ; this.vertical그 불리언 값으로 설정됩니다. 그렇지 않으면 동일하게 유지됩니다. 나는 그 자체로 당신이 사용하는 방법 !!과 그것을 하는 방법의 예라고 생각합니다 .


수직 I / O 예제

이 예제를 실행하고 입력에서 수직 값을 가지고 주변을 돌리십시오. 결과가 어떤 결과를 가져와 컨텍스트의 코드를 완전히 이해할 수 있는지 확인하십시오. 입력에서 유효한 javascript 값을 입력하십시오. 문자열을 테스트하는 경우 인용 부호를 포함해야합니다. CSS와 HTML 코드를 너무 많이 신경 쓰지 마라. 간단히이 스 니펫을 실행하고 그 코드를 가지고 놀아 라. 그러나 비 DOM 관련 자바 스크립트 코드 (Example 생성자 및 세로 변수 사용)를 살펴볼 수도 있습니다.

var vertical = document.getElementById("vertical");
var p = document.getElementById("result");

function Example(vertical)
{
        this.vertical = vertical !== undefined ? !!vertical : 
        this.vertical;   

        return this.vertical;
}

document.getElementById("run").onclick = function()
{

  p.innerHTML = !!( new Example(eval(vertical.value)).vertical );
  
}
input
{
  text-align: center;
  width: 5em;
} 

button 
{
  margin: 15.5px;
  width: 14em;
  height: 3.4em;
  color: blue;
}

var 
{
  color: purple;
}

p {
  margin: 15px;
}

span.comment {
  color: brown;
}
<!--Vertical I/O Example-->
<h4>Vertical Example</h4>
<code id="code"><var class="var">var</var> vertical = <input type="text" id="vertical" maxlength="9" />; <span class="comment">// enter any valid javascript value</span></code>
<br />
<button id="run">Run</button>
<p id="result">...</p>


!!expr 은 표현의 진실성 에 따라 부울 값 ( true 또는 false )을 반환합니다. 부울이 아닌 유형에서 사용될 때 더 유용합니다. 다음 예제를 고려하십시오. 특히 3 번째 예와 그 이후 :

          !!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!

!!xBoolean(x) 약자입니다.

첫 번째 뱅은 js 엔진에 Boolean(x) 을 강제 실행하지만 값을 반전하는 부작용도 있습니다. 그래서 두 번째 강타는 부작용을 취소합니다.


Boolean() 캐스팅 함수의 동작을 시뮬레이트합니다. 첫 번째 NOT 은 주어진 피연산자와 상관없이 부울 값을 반환합니다. 두 번째 NOTBoolean 값을 무효화하므로 변수의 true 부울 값을 제공합니다. 최종 결과는 값에 Boolean() 함수를 사용하는 것과 같습니다.


oObject 를 boolean으로 변환합니다. false (0, null , undefined 등) 인 경우 false , 그렇지 않은 경우 true 입니다.

!oObject  //Inverted boolean
!!oObject //Non inverted boolean so true boolean representation

그래서 !! 연산자가 아니에요, 그냥 ! 연산자를 두 번.

실제 세계 예제 "Test IE version":

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

너라면 ⇒

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns null  

하지만 너라면 ⇒

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

일부 차를 양조하십시오.

!! 연산자가 아닙니다. 그것의 이중 사용이다 ! - 논리적 "not"연산자입니다.

이론에 의하면:

! 가치가 아닌 것의 "진리"를 결정합니다.

  • 진실은 falsetrue 이 아니라는 것 true (그 이유는 true )

  • 진실은 진실은 false 이 아니라는 것입니다 (그것이 true 입니다)

!! 가치가 아닌 것의 "진리"를 결정합니다 :

  • 진실은 진실이 진실이 아니라는 true 입니다.

  • 진실은 falsefalse 이 아니라는 것입니다 (즉, false!!false 결과입니다)

우리가 비교에서 결정하고자하는 것은 참조 자체의 가치가 아니라 참조 값에 대한 "진실"입니다. 값을 false (또는 false )로 예상하거나 값이 boolean 아닐 것으로 예상하는 경우에도 값에 대한 진실을 알고 자 할 수있는 유스 케이스가 있습니다.

실제로:

동적 타이핑 (일명 "오리 타이핑")을 통해 피쳐 기능 (이 경우 플랫폼 호환성)을 감지하는 간결한 기능을 고려하십시오. 사용자 브라우저가 HTML5 <audio> 요소를 지원하는 경우 true 를 반환하는 함수를 작성하려고하지만 <audio> 가 정의되지 않은 경우 함수가 오류를 발생시키지 않도록해야합니다. 가능한 모든 오류를 처리하기 위해 try ... catch 를 사용하고 싶지 않습니다 (총칭이기 때문에). 또한 기능에 대한 진실을 일관되게 나타내지 않는 함수 내부에서 검사를 사용하지 않으려합니다 (예 : document.createElement('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

각 함수는 <tag> 대한 인수와 찾아야 할 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

우리는 ...

드물지만 이러한 상황이있을 수 있습니다. 가장 간단하고, 성능이 뛰어나며, 따라서 부울이 아닌 값, 정의되지 않은 값에서 참이되는 가장 바람직한 방법이 실제로 사용되는 몇 가지 시나리오가있을 수 있습니다 !! . 희망적으로이 말도 안되게 그것을 지 웁니다.







operators