Zamboni
Zamboni

Reputation: 335

Why use double exclamation marks in an if statement?

I have recently read some code that uses !! to convert a variable to boolean for evaluation in an if statement. This seems somewhat redundant to me as the variable would be evaluated for its boolean value anyway. Are there any performance benefits to doing this or is it for better browser support?

Sample Code:

var x = 0;
var atTop = x===window.scrollY;
if(!!atTop){
   alert("At the top of the page.");
}

Edit:

I have also seen this for operands that are not of boolean types, but I had always assumed that using if would evaluate the boolean value of the variable anyway as all values in Javascript are either "truthy" or "falsey".

Sample Code:

var x = 1;//or any other value including null, undefined, some string, etc
if(!!x){//x is "truthy"
   //wouldn't using if(x) be the same???
   console.log("something...");
}

Upvotes: 18

Views: 14703

Answers (4)

P.S.
P.S.

Reputation: 16384

Short answer: No, there is no reason.

In your code, it's already a boolean type, there is no need to convert, and convert it back again: you will always get the same result. Actually, if you have a boolean value (true or false), when you use !! with any of them, it will be converted back to its original value:

console.log(!!true); // Will always be "true"
console.log(typeof !!true); // It's still a "boolean" type
console.log(!!false); // Will always be "false"
console.log(typeof !!false); // It stills a "boolean" type

Answer for edited question: Yes, it's the same. That's what if(...) actually does - it's trying to convert any type to boolean.

Here is a small test, you can play around with that and add whatever you want inside the initialArr array in order to test whether it behaves the same with if and !!:

const initialArr = [
  undefined,
  null,
  true,
  false,
  0,
  3,
  -1,
  +Infinity,
  -Infinity,
  Infinity,
  'any',
  '',
  function() { return 1 },
  {},
  { prop: 1 },
  [],
  [0],
  [0, 1]
];

function testIsTheSame(arr) {
  let equolityCounter = 0;
  
  arr.forEach(item => {
    let ifStatement = false;
    let doubleNotStatement = !!item;
    
    if (item) {
      ifStatement = true;
    }

    if (
      ifStatement === doubleNotStatement &&
      typeof ifStatement === typeof doubleNotStatement
    ) {
      equolityCounter++;
    }
  });
  
  console.log(`Is the same: ${equolityCounter === arr.length}`);
}

testIsTheSame(initialArr);

Upvotes: 13

Ben Barkay
Ben Barkay

Reputation: 5632

There isn't any run-time benefit (or an objective one) whatsoever to doing this in an if statement. The evaluation performed by the if statement will yield precisely the same result as the evaluation produced by double exclamation mark. There is no difference.

Double exclamation marks is a useful expression to ensure boolean value based on truthyness. Consider, for instance:

var text = undefined;
console.log(text); // undefined
console.log(!!text); // false

// It would make sense here, because a boolean value is expected.
var isTextDefined = !!text;

// It would also affect serialization
JSON.stringify(text); // undefined (non-string)
JSON.stringify(!!text); // "false"

I suppose that this is a habit that was picked up because of the above use cases, thus always converting to boolean when wishing to address a variable's truthyness. It's easier for us (humans and programmers) to follow a rule when it's always applied. You'll either use the blinkers in your car all the time, even when there's nobody around, or it's likely that you'll occasionally (or maybe often) forget to signal when you should have.

Upvotes: 5

Luis Art Guerra
Luis Art Guerra

Reputation: 364

It all depends on the value of atTop variable. Follow the discussion here.

In summary, if the value of atTop is anything different to a boolean, the first negation will convert it to a boolean value (negated). Second negation will return the boolean value to the equivalent boolean of the original atTop value.

For example, if atTop is undefined, first ! will turn it to boolean true, then the second ! turns it to boolean false (which would be the equivalent boolean of undefined)

However, in your code the atTop value is the result of an strict equality ===, which means you always get a boolean as a result in atTop. Thus, you don't need to convert a non-boolean value to boolean, and so, the !! is not needed.

Upvotes: 1

Thymine
Thymine

Reputation: 9205

I would say it was mostly done for code-readability. I doubt there is any significant performance nor compatibility implications (someone feel free to test this please)

But in the code-readability aspect, it would imply to me that this variable previously was not a boolean, but we want to evaluate it as one, if you add new logic concerning this variable, keep that in mind.

Although in your case its already boolean, so its 100% redundant, but I'd guess just a habit of someone for the above reasoning applied excessively, and/or seeing it elsewhere and copying that pattern without fully understanding it (short story time: in C# you can name a protected term a variable name by adding @, so var @class = "hello";, a junior dev just assumed all variable names needed @ in front of them, and coded that way. I wonder if someone assumed that an if without a comparison operator needs to have !! in front of it as a comparison operator)

Upvotes: 3

Related Questions