JavaScript: The ❕unary operator

Chidume Nnamdi 🔥💻🎵🎮
Dev Proto
Published in
5 min readJul 30, 2020

! is a Logical operator commonly used in JavaScript. Despite its wide usage, only a few understand what it does.

So, I took time out in this post to describe what ! does and how it works.

! That’s an exclamation mark

! is a logical NOT operator, placing the ! operator in front of a value will convert it to a Boolean and return the opposite value. So truthy values will return false, and falsy values will return true. This is known as negation:

const yes = true
const neg = !yes
l(neg) // false

yes is a boolean true, but returned its negative form, false, when we prefixed ! to it. neg logs false.

If we prefix ! at neg, it will return true

const yes = true
const neg = !yes
l(neg) // false
l(!neg) // true

! returns the opposite of the boolean value it was given.

Let’s see more examples:

l(!"")
l(![])
l(!true)
l(!false)
l(!{})
l(!NaN)
l(!null)
l(!undefined)
l(!0)
l(!function(){})
l(!"0")
l(!"false")

Logs:

true
false
false
true
false
true
true
true
true
false
false
false

We have to understand something here. There are truthy and falsy values in JS. That is, some expressions and statements resolves to true or false.

Let’s look at the EcmaSpec for the unary ! operator:

First 1. the expression at the RHS of the ! operator is evaluated.

!2

2 is the expression here. It is evaluated before ! will be operated on it.

!(3+8)

(3+8) is the expression here that will be evaluated (11) before the ! will be operated on the result.

2. The result of the expression evaluation will be gotten using the GetValur method. Then the result will be converted to boolean primitive value using the ToBoolean method.

Let’s see the spec for ToBoolean:

Here, we see the argument type and the result of each. This ToBoolean method converts all primitive types and objects to the boolean primitive(either true or false).

undefined and null both converts to false.

If the argument is a boolean primitive, no need for conversion it returns itself.

For number, it says that if the argument is

+0, -0, or NaN

it should return false, apart from these it should return true for any other number.

For string, only empty strings return false, others are true.

Symbols and objects return true.

With this we can say that the falsy values in JS are:

  • false
  • 0 (zero)
  • ‘’ or “” (empty string)
  • null
  • undefined
  • NaN

Back to Logical NOT spec

3. the result of the ToBoolean is checked. if the result is true, false will be returned.

4. returns true if the ToBoolean is false.

With this information, you can guess what the above will each yield.

l(!"")
l(![])
l(!true)
l(!false)
l(!{})
l(!NaN)
l(!null)
l(!undefined)
l(!0)
l(!function(){})
l(!"0")
l(!"false")

Let’s follow the Logical NOT spec on each of them

!””

The expression will be “”. It is a string, an empty string. The ToBooean when called on it, says to return false if the argument is a string and empty.

So false will be returned, then logical not will return true because the result of the ToBoolean is false.

!"" // false

![]

[] is an array, yes and its an object. So, ToBoolean of [] will return true, and Logical NOT will return false.

!true

ToBolean of true will return true, true is boolean primitive so no conversion needed ToBoolean will just return it.

Logical NOT will then, return false

!false

false is already a boolean primitive, so ToBoolean will return it. Logical NOT will then return true following that ToBoolean returned false.

!false // true

!{}

ToBoolean called passing in {} will return true. {} is an object (an empty object), objects return true, so {} returns true. Remember this: Despite being an empty object, {} resolves to true, unlike empty string that resolves to false.

Logical NOT will then return false.

!{} // false

That means this hand_down_emoji will resolve to true:

const obj = {}
if(obj) {
...
}

The if statement will pass the obj to ToBoolean which will return true because {} is an object and so the if statement body will run.

!NaN

ToBoolean of NaN says to return false. And so, Logical NOT will return true.

!NaN // true

!null

ToBoolean of null says to return false, so Logical NOT will see false and return true.

!null // undefined

!undefined

Same here, ToBoolean says to return false on undefined. So, Logical NOT will return true.

!undefined

!0

0 is number but ToBoolean says a +0 returns false, so Logical NOT returns true.

!0 // true

!function(){}

functions are resolved to objects, so ToBoolean will see an object and return true. Logical NOT then returns false.

!function() {} // false

!”0"

This “0” is a string with a length of 1. Many will think this will be evaluated to zero (0) number. No, this is a string containing the number 0. ToBoolean will return true on it, yes, it is not an empty string.

Logical NOT seeing true will return false.

!"0" // false

!”false”

Also, this is a string with length 5. This will not be evaluated to boolean false or evaluated to an empty string.

If we split it into an array it would give [“f”,”a”,”l”,”s”,”e”]

So ToBoolean will see a string with length 5 and returns true.

Logical NOT will then return false:

!"false" // true

See, we followed the spec on each of them to see why they yield the results.

Double Negation

This is the placing of double !! on an expression.

!!true // true

It negates the negation.

There is no magic or complex stuff going on here. It is just applying Logical Not ! on the result of the initial Logical Not operation.

!!true

is same as

!(!true)

Logical Not is first applied to !true, the result is false. Then, another Logical Not is applied to the result false, which yields true.

Double Logical NOTs !! is useful in finding out whether a value is truthy or falsy. It is a shortcut to using the Boolean function because !! is effectively negating the negation.

Conclusion

We have seen how !! works underneath, how it does its conversion and returns a result.

The EcmaSpec is always there, with the answers if we find anything confusing in JavaScript.

If you have any questions regarding this or anything I should add, correct or remove, feel free to comment, email or DM me.

Thanks !!!

Thanks for stopping by my little corner of the web. I think you’ll love my email newsletter about programming advice, tutoring, tech, programming and software development. Just sign up below:

Follow me on Twitter.

--

--

Chidume Nnamdi 🔥💻🎵🎮
Dev Proto

JS | Blockchain dev | Author of “Understanding JavaScript” and “Array Methods in JavaScript” - https://app.gumroad.com/chidumennamdi 📕