JavaScript에서“!-”는 무엇을합니까?


376

이 코드 조각이 있습니다 ( 이 질문 에서 가져 왔습니다 ).

var walk = function(dir, done) {
    var results = [];

    fs.readdir(dir, function(err, list) {
        if (err)
            return done(err);

        var pending = list.length;

        if (!pending) 
            return done(null, results);

        list.forEach(function(file) {
            file = path.resolve(dir, file);
            fs.stat(file, function(err, stat) {
                if (stat && stat.isDirectory()) {
                    walk(file, function(err, res) {
                        results = results.concat(res);

                        if (!--pending)
                            done(null, results);
                    });
                } else {
                    results.push(file);

                    if (!--pending) 
                        done(null, results);
                }
            });
        });
    });
};

나는 그것을 따르려고 노력하고 있으며, 나는 그것이 끝나는 끝을 제외하고는 모든 것을 이해한다고 생각합니다 !--pending. 이러한 맥락에서 그 명령은 무엇을 하는가?

편집 : 추가 의견을 보내 주셔서 감사하지만 질문에 여러 번 대답했습니다. 어쨌든 고마워!


222
코드를 유지하기 위해 다음 사람을 혼동하는 훌륭한 방법입니다.
— Eric J.

240
!~--[value] ^ true이 "고용 안정"과 같은 I 호출 코드
— TbWill4321


36
@ TbWill4321 코드 검토를 수행하는 경우 작업 보안과 정반대입니다.
— corsiKa December

8
변수 이름과 결합 된 연산자는 그리 나쁘지 않습니다. 노련한 자바 스크립트 프로그래머라면 그 기능을 알기 위해 몇 초 이상이 필요하지 않습니다.
— Christiaan Westerbeek

답변:


537

! 값을 반전시키고 반대의 부울 값을 제공합니다.

!true == false
!false == true
!1 == false
!0 == true

--[value] 숫자에서 1을 빼고 작업 할 수를 반환합니다.

var a = 1, b = 2;
--a == 0
--b == 1

따라서 !--pending보류 중 하나를 뺀 다음 진실 / 거짓 값의 반대 값을 반환합니다 (여부에 관계없이 0).

pending = 2; !--pending == false 
pending = 1; !--pending == true
pending = 0; !--pending == false

네, ProTip을 따르십시오. 이것은 다른 프로그래밍 언어의 일반적인 관용어 일 수 있지만 대부분의 선언적 JavaScript 프로그래밍의 경우 꽤 외계인처럼 보입니다.


623
ProTip ™ : 코드에서이 작업을 수행하지 마십시오.
— Naftuli Kay

17
--변수에만 작용 하는 것은 언급하지 않습니다 . 일반적인 값에는 적용 할 수 없습니다.
— deltab

10
@deltab : validSimpleAssignmentTargets, 정확합니다. 여기에는 식별자 참조 및 속성 참조가 포함됩니다.
— Bergi

19
--0및 --1작동하지 않습니다. 숫자 리터럴은 유효한 왼쪽 표현이 아닙니다
— PSWai

7
@Pharap : 어, 그 i > -1것보다 파싱하는데 더 많은 문제가 i--있습니다 i = init() - 1. 이것이 관용구입니다… 그리고 모든 프로그래머는 그것들을 배워야합니다.
— Bergi

149

그것은 특별한 연산자가 아니며, 두 개의 표준 연산자입니다.

  1. 접두사 감소 ( --)
  2. 논리적이지 않은 ( !)

이로 인해 pending감소한 다음 0인지 확인하기 위해 테스트됩니다.


8
나는 이것에 익숙하지 않지만 왜 이것을 사용하는 것보다 우수 if(pending === 1)합니까?
— Kieran E

46
@KieranE, "가독성은 왕이다"라는 규칙을 완전히 어기는 것은 속기입니다.
— Ryan

23
@KieranE 그것은 우월하다는 것이 아니라 다릅니다. 변수를 변경 (1 씩 감소) 한 다음 새로운 값을 사용하여 테스트
— Amit

7
@KieranE와 동일합니다 if( pending === 1 ) { done... } else { pending = pending - 1; }.
— CompuChip

7
@CompuChip 실제로 --pending은 어떤 경우에도 수행되므로 코드는 다음과 같습니다. if (! pending) {--pending; etc.} else {-보류 중; etc.} 이것은 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…를
— Paul Russell

109

답변의 숫자는 설명 어떤 이 명령하지,하지만 왜 그것을 여기에서 그런 식으로 이루어집니다.

나는 C 세계에서 왔으며, 실제로 생각하지 않고 !--pending"카운트 다운 pending하고 0인지 확인 "으로 읽 습니다. 비슷한 언어의 프로그래머가 알아야 할 관용구입니다.

이 함수는 readdir파일과 서브 디렉토리 목록을 가져 오는 데 사용 하며,이를 총칭하여 "항목"이라고합니다.

변수 pending는 처리 될 남아있는 수를 추적합니다. 목록의 길이로 시작하여 각 항목이 처리 될 때 0을 향해 아래로 계산됩니다.

이러한 항목은 순서가 잘못 처리 될 수 있으므로 단순한 루프를 사용하는 대신 카운트 다운해야합니다. 때 모든 항목이 처리 된 콜백 done이 사실상 원래 호출자에게 통지하기 위해 호출된다.

첫 번째 호출에서 done앞에 접두사가 붙습니다 return. 값을 반환하려는 것이 아니라 단순히 그 시점에서 함수 실행을 중지시키기 위해서입니다. 를 삭제 return하고에 대안을 넣는 것이 더 깨끗한 코드 일 것 else입니다.


13
@Bergi는 C 세계에서 잘 알려진 관용어이지만 관용적 인 자바 스크립트 는 아닙니다 . 주어진 하위 표현에 대해 서로 다른 생태계에는 '어떻게 수행'되는지에 따라 서로 다른 서로 호환되지 않는 관용구가 있습니다. '외국어'언어의 관용구를 사용하는 것은 다소 나쁜 코드 냄새입니다.
— Peteris

3
@Peteris : 감소 연산자가있는 모든 C 유사 언어의 관용구입니다. 물론 언어에 따라 다른 더 나은 방법이 있지만 JS에는 특별한 계산 관용구가 있다고 생각하지 않습니다.
— Bergi

6
Javascript 커뮤니티에는 Douglas Crockford와 같은 영향력있는 리더를 포함하여 상당수의 단항 증가 및 감소 연산자를 피하는 것을 옹호하는 상당 부분이 있습니다 . 나는 그들이 정확한지 아닌지에 대해서는 여기서 논쟁하지 않을 것이다. 내 의도는 논쟁이 존재하기 때문에 코드와 같은 코드 !--pending는 많은 린터와 스타일 지침에 실패 한다는 것 입니다. 그것은 대안이 "더 나은지"에 관계없이 관용적이지 않다고 말하기에 충분합니다.
— GrandOpener

3
@GrandOpener "관용적"은 "원어민이 일반적으로 이해하는 표현"을 의미합니다. C와 같은 언어 사용자 는 사전 감소를 확실히 이해하고 있으며 확장하여 "! (-x)"도 마찬가지입니다. 무언가를 사용하는 것이 Good Idea® 인지의 여부 는 전적으로 관용적 인 방식과는 별개의 질문입니다. (예를 들어, 코드에 코드를 포함시키는 것이 목록에있는 "Lust"와 "Murder"사이에 있다고 자주 표현되는 의견에도 불구하고 "goto"가하는 일을 이해하지 못하는 모든 언어의 많은 프로그래머를 만나게 될 것입니다. 치명적인 죄의 8).
— jmbpiano

3
의는 C # 및 Java 변환하지 않기 때문에 그건 @Pharap int에 bool암시 적으로, 그리고 사용과는 전혀 무관하다 !--.
— Agop

36

속기입니다.

! 아니다".

-- 값을 줄입니다.

따라서 !--값 감소 결과를 무효화하여 얻은 값이 false인지 확인합니다.

이 시도:

var x = 2;
console.log(!--x);
console.log(!--x);

x의 값이 1이므로 두 번째는 true입니다. x의 값은 0이므로 첫 번째는 false입니다.

참고 사항 : !x--x가 먼저 false인지 확인한 다음 감소시킵니다.


사이드 노트 다시-확실합니까? post-fix가 우선 순위가 높은 !반면 post-fix가 우선 순위가 높은 것 같습니다 . JavaScript 운영자 우선 순위
— Dannnno

2
예. (보십시오 var x = 2; console.log(!x--); console.log(!x--); console.log(!x--);). 사후 수정 --이 먼저 실행될 수 있지만 리턴 값은 감소하기 전의 변수 값 ( Decrement Opperator )입니다.
— Lucas

" !--값을 줄인 결과의 부정을 반환합니다." 와 같은 외부 코드 만 console.log()내용이 진실인지 확인합니다.
— mareoraft

31

!JavaScript NOT 연산자입니다

--사전 감소 연산자입니다. 그래서,

x = 1;
if (!x) // false
if (!--x) // becomes 0 and then uses the NOT operator,
          // which makes the condition to be true

8
WTH는 "거짓 진술"입니까?
— Bergi

5
@ Bergi 나는 그것이 의미하는 바를 실제로 알고 있다고 가정하지만, 당신이 (또는 다른 사람이하지 않는 경우) 이 개념을 가진 다른 언어 (예 : Python)로 다소 잘 번역 되는 JavaScript에 대한 설명 이 있습니다.
— Dannnno

1
@Parap 그것은 내 대답이 아니므로 만지지 않을 것입니다.
— Dannnno

2
@Dannnno : 글쎄, 나는 잘못된 값이 무엇인지, 어떤 문장 이 무엇인지 알고 있으므로 JS에는 "false statement"와 같은 것이 없다는 것을 알고 있습니다. 나는 이것이 논리 용어를 언급하지 않는다고 가정한다 .
— Bergi

1
어떻게 '이해가 안 --연산자는 상수와 함께 일할 수 어쩌면 당신이 의미 ... --x대신 --0?
— SJuan76

24
if(!--pending)

방법

if(0 == --pending)

방법

pending = pending - 1;
if(0 == pending)

4
그리고 그 코드를 작성하는 분명한 방법입니다. 물론 if(0 == pending)오타의 가능성 때문에 선호 합니다. if(0 = pending)구문 오류입니다. if(pending = 0)완성 된 코드에서 혼동을 일으키는 할당입니다.
— Theo Brinkman

3
@TheoBrinkman : 실제로 if(0 = pending)는 구문 오류가 아닙니다. 파싱이 잘됩니다. 그러나 0할당 할 수 없기 때문에 참조 오류 입니다 (ECMA-262 (6 번째) 초 12.14.1 참조).
— hmakholm 님이 Monica에서

13

적절한 운영자가 아닌 사전 운영자입니다.

따라서 pending값이 1 인 정수인 경우

val = 1;
--val; // val is 0 here
!val // evaluates to true

11

그것은 단지 pending1 씩 감소 하고 논리적 보완 (음수)을 얻습니다. 0과 다른 숫자의 논리 보수는 false0이므로 0입니다 true.


"부
— 정권

1
좋아, 나는 다른 용어를 사용할 것이다. 이것이 더 나은지 확실하지 않습니다.
— MinusFour

11

설명

이 연산자는 a !와 a--

!--x 

따라서 --x를 1 씩 줄인 다음 !x가 이제 0 (또는 NaN ...)이면 true를 반환하고 그렇지 않으면 false를 반환합니다. 이 관용구를 "x를 줄이면 0으로 만듭니다."

더 읽기 쉽게하려면 다음을 수행하십시오.

var x = 1
x = x - 1   
if(!x){ //=> true
    console.log("I understand `!--` now!") 
}
x //=> 0

사용해보십시오 :

/* This is an example of the above, you can read this, but it is not needed for !-- */function interactive(a){$("span.code").keydown(function(e){if(13==(e.keyCode||e.which)){var t=$(this);t.clone().html("code").insertAfter(t.next().next()).show().focus().after(template.clone().removeClass("result-template").show()).next().after("<br>"),interactive(),e.preventDefault()}}).keyup(function(e){13!=(e.keyCode||e.which)&&run()})}var template=$(".result-template").hide(),code=$("span.code");code.attr("contenteditable","true").each(function(e,t){template.clone().removeClass("result-template").insertAfter(t)}),interactive(),$.fn.reduce=[].reduce;function run(){var b=!1,context={};$("span.code").each(function(){var a=$(this),res=a.next().show().removeClass("error");try{with(context)res.html(b?"":"  //=> "+eval(a.text()))}catch(e){b=e,res.html("  Error: "+b.message).addClass("error")}})};run();
/* This is an example of the above, you can read this, but it is not needed for !-- */span.result.error{display:block;color:red}.code{min-width:10px}body{font-family:Helvetica,sans-serif}
<!-- This is an example of the above, you can read this, but it is not needed for `!--` --><span class="result result-template"> //=> unknown </span> <h2>Edit This Code:</h2><code><span class="code">x = 1</span><br><span class="code">!--x</span><br><span class="code"> x </span><br></code> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

피들 (시험해보기)


8

여기서 실제 문제는 두 연산자 !와 사이에 공백이 없다는 것입니다 --.

나는 사람들이 왜 머리 뒤에 그것을 넣었는지 모르겠다 !. 나는 그것이 상식 대신 기계적인 공백 규칙을 엄격하게 적용하여 나온 것이라고 생각합니다. 내가 본 모든 코딩 표준은 단항 연산자 뒤에 공백을 금지하지만 왜 그럴까요?

그 공간이 분명히 필요한 경우가 있다면 , 이것은 하나입니다.

이 코드 비트를 고려하십시오.

if (!--pending)
    done(null, results);

함께 !하고 --으깬 것 뿐만 아니라( 도 그들에 대해 비난을 . 무엇이 무엇에 연결되어 있는지 말하기가 어렵습니다.

공백이 조금 더 있으면 코드가 훨씬 명확 해집니다.

if( ! --pending )
    done( null, results );

물론, "안개 안에 공간 없음"과 "단항 연산자 뒤에 공간 없음"과 같은 기계적인 규칙에 익숙하다면 약간 이질적인 것처럼 보일 수 있습니다.

그러나 어떻게 보는가에 여분의 공백 그룹과 분리의 여러 부분 if문장과 표현 : 당신이있어 --pending(가) 때문에, --명확하게 자신의 연산자와 밀접하게 연결되어 있습니다 pending. ( pending감소 된 결과를 감소 시키고 리턴합니다.) 그런 다음 그로부터 !분리되어 결과를 무시하는 명백한 연산자입니다. 마지막으로, 당신은 가지고 if(와 )전체 표현식을 둘러싼 것은 그것에게 수 있도록 if문.

그리고 네, 나는 사이의 공간을 제거 if하고 ((가) 때문에, ( 속한 받는 사람 if. 이것은 문장 자체 의 구문의 일부인 원본에있는 것처럼 보이는 (일종의 (!--구문 의 일부가 아닙니다 .(if

여기서 공백은 기계적 코딩 표준을 따르는 대신 의미 를 전달하는 역할을 합니다.


1
공백 버전은 더 읽기 쉽습니다. 내가 처음 질문했을 때 내가 !--알지 못하는 자바 스크립트 연산자라고 생각했다. 더 명확하게 괄호를 사용하지 않는 이유는 무엇입니까? if(!(--pending))
— emory

1
스타일 가이드는 ++또는 사용 금지를 알고 --있지만 접두사 연산자 다음과 같이 비 필수 공백 및 비 필수 괄호 사용 은 금지 !합니다.

1
단항 연산자 다음의 공백은 작동하는 표현식과 구분되므로 사용하지 않는 것이 좋습니다. 당신은 그것을 함께 읽고 싶을 것입니다 ... 적어도 imho
— aldrin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.