[javascript] What is the !! (not not) operator in JavaScript?

!! is similar to using the Boolean constructor, or arguably more like the Boolean function.

_x000D_
_x000D_
console.log(Boolean(null)); // Preffered over the Boolean object_x000D_
_x000D_
console.log(new Boolean(null).valueOf()); // Not recommended for coverting non-boolean values_x000D_
_x000D_
console.log(!!null); // A hacky way to omit calling the Boolean function, but essentially does the same thing. _x000D_
_x000D_
_x000D_
// The context you saw earlier (your example)_x000D_
var vertical;_x000D_
_x000D_
function Example(vertical)_x000D_
{_x000D_
        this.vertical = vertical !== undefined ? !!vertical : _x000D_
        this.vertical; _x000D_
        // 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).   _x000D_
_x000D_
        return this.vertical;_x000D_
}_x000D_
_x000D_
console.log( "\n---------------------" )_x000D_
_x000D_
// vertical is currently undefined_x000D_
_x000D_
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical_x000D_
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical_x000D_
_x000D_
vertical = 12.5; // set vertical to 12.5, a truthy value._x000D_
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be true anyway_x000D_
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical_x000D_
_x000D_
vertical = -0; // set vertical to -0, a falsey value._x000D_
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be false either way_x000D_
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical
_x000D_
_x000D_
_x000D_

Falsey values in javascript coerce to false, and truthy values coerce to true. Falsey and truthy values can also be used in if statements and will essentially "map" to their corresponding boolean value. However, you will probably not find yourself having to use proper boolean values often, as they mostly differ in output (return values).

Although this may seem similar to casting, realistically this is likely a mere coincidence and is not 'built' or purposely made for and like a boolean cast. So let's not call it that.


Why and how it works

To be concise, it looks something like this: ! ( !null ). Whereas, null is falsey, so !null would be true. Then !true would be false and it would essentially invert back to what it was before, except this time as a proper boolean value (or even vice versa with truthy values like {} or 1).


Going back to your example

Overall, the context that you saw simply adjusts this.vertical depending on whether or not vertical is defined, and if so; it will be set to the resulting boolean value of vertical, otherwise it will not change. In other words, if vertical is defined; this.vertical will be set to the boolean value of it, otherwise, it will stay the same. I guess that in itself is an example of how you would use !!, and what it does.


Vertical I/O Example

Run this example and fiddle around with the vertical value in the input. See what the result coerces to so that you can fully understand your context's code. In the input, enter any valid javascript value. Remember to include the quotations if you are testing out a string. Don't mind the CSS and HTML code too much, simply run this snippet and play around with it. However, you might want to take a look at the non-DOM-related javascript code though (the use of the Example constructor and the vertical variable).

_x000D_
_x000D_
var vertical = document.getElementById("vertical");_x000D_
var p = document.getElementById("result");_x000D_
_x000D_
function Example(vertical)_x000D_
{_x000D_
        this.vertical = vertical !== undefined ? !!vertical : _x000D_
        this.vertical;   _x000D_
_x000D_
        return this.vertical;_x000D_
}_x000D_
_x000D_
document.getElementById("run").onclick = function()_x000D_
{_x000D_
_x000D_
  p.innerHTML = !!( new Example(eval(vertical.value)).vertical );_x000D_
  _x000D_
}
_x000D_
input_x000D_
{_x000D_
  text-align: center;_x000D_
  width: 5em;_x000D_
} _x000D_
_x000D_
button _x000D_
{_x000D_
  margin: 15.5px;_x000D_
  width: 14em;_x000D_
  height: 3.4em;_x000D_
  color: blue;_x000D_
}_x000D_
_x000D_
var _x000D_
{_x000D_
  color: purple;_x000D_
}_x000D_
_x000D_
p {_x000D_
  margin: 15px;_x000D_
}_x000D_
_x000D_
span.comment {_x000D_
  color: brown;_x000D_
}
_x000D_
<!--Vertical I/O Example-->_x000D_
<h4>Vertical Example</h4>_x000D_
<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>_x000D_
<br />_x000D_
<button id="run">Run</button>_x000D_
<p id="result">...</p>
_x000D_
_x000D_
_x000D_