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 intbool암시 적으로, 그리고 사용과는 전혀 무관하다 !--.
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.