What does “!--” do in JavaScript?

旧时模样 提交于 2019-11-28 14:56:44

! inverts a value, and gives you the opposite boolean:

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

--[value] subtracts one (1) from a number, and then returns that number to be worked with:

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

So, !--pending subtracts one from pending, and then returns the opposite of its truthy/falsy value (whether or not it's 0).

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

And yes, follow the ProTip. This may be a common idiom in other programming languages, but for most declarative JavaScript programming this looks quite alien.

Amit

That's not a special operator, it's 2 standard operators one after the other:

  1. A prefix decrement (--)
  2. A logical not (!)

This causes pending to be decremented and then tested to see if it's zero.

A number of answers describes what this command does, but not why it is done that way here.

I come from the C world, and I read !--pending as "count down pending and check if it is zero" without really thinking about it. It is an idiom that I think programmers in similar languages should know.

The function uses readdir to get a list of files and subdirectories, which I will collectively call "entries".

The variable pending keeps track of how many of these remains to be processed. It starts out as the length of the list, and counts downward towards zero as each entry is processed.

These entries may be processed out of order, which is why it is necessary to count down rather than just using a simple loop. When all the entries have been processed the callback done is called to notify the original caller of this fact.

In the first call to done is prepended with return, not because we want to return a value, but simply to make the function stop executing at that point. It would have been cleaner code to drop the return and put the alternative in an else.

It's a shorthand.

! is "not".

-- decrements a value.

So !-- checks if the value obtained from negating the result of decrementing a value is false.

Try this:

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

The first is false, since the value of x is 1, the second is true, since the value of x is 0.

Side note: !x-- would check if x is false first, and then decrement it.

Sterling Archer

! is the JavaScript NOT operator

-- is a pre-decrement operator. So,

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

means

if(0 == --pending)

means

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

It's the not operator followed by the in-place pre-decrementer.

So if pending was an integer with a value of 1:

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

Explanation

This is 2 operators, a ! and a --

!--x 

So, this detriments x by 1, and checks to see if it's a boolean.

If you wanted to make it more readable, you can:

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

Try it out:

/* 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>

Fiddle (Try Out Code)

It merely decreases pending by one and obtains its logical complement (negation). The logical complement of any number different than 0 is false, for 0 it is true.

The real problem here is the lack of a space between the two operators ! and --.

I don't know why people get it in their heads that you can't ever use a space after the ! operator. I think it comes from rigid application of mechanical whitespace rules instead of common sense. Just about every coding standard I've seen prohibits spaces after all unary operators, but why?

If there were ever a case where you clearly need that space, this is one.

Consider this bit of code:

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

Not only are ! and -- mashed together, you've got that ( slammed against them too. No wonder it's hard to tell what is connected to what.

A bit more whitespace makes the code much more clear:

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

Sure, if you're used to mechanical rules like "no space inside parens" and "no space after a unary operator", this may seem a bit foreign.

But look at how the extra whitespace groups and separates the various parts of the if statement and expression: You've got --pending, so the -- is clearly its own operator and is tied closely to pending. (It decrements pending and returns the decremented result.) Then you've got the ! separated from that so it's obviously a distinct operator, negating the result. Finally, you've got if( and ) surrounding the whole expression to make it an if statement.

And yes, I removed the space between if and (, because the ( belongs to the if. This ( isn't part of some kind of (!-- syntax as it appears to be in the original, the ( if part of the syntax of the if statement itself.

The whitespace here serves to communicate the meaning, instead of following some mechanical coding standard.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!