Skip to content

Instantly share code, notes, and snippets.

@arthurvi
Last active October 10, 2024 15:44
Show Gist options
  • Save arthurvi/66cb1e2bcfc92f99f465e0db04264367 to your computer and use it in GitHub Desktop.
Save arthurvi/66cb1e2bcfc92f99f465e0db04264367 to your computer and use it in GitHub Desktop.
!! vs. Boolean()

Boolean() or !! (double bang, double negation)?

What's the best way to answer the question "true or false?" in JavaScript

JavaScript does not bother you too much with types (at first), which is both a blessing and a cure. But we all know the Boolean type. Boolean variables can either be true or false. Yes or no.

Every value in JavaScript can be translated into a boolean, true or false. Values that translate to true are truthy, values that translate to false are falsy. Simple.

This is about two ways to make that translation.

!! and Boolean()

const value = 'hello world';

Boolean(value); // true - the boolean function
!!value; // true - double bang / double negation

Which one is the best?

Truthy and Falsy

The conversion from any value to true or false is described by the abstract operation ToBoolean in section 9.2 of the ECMAScript® Language Specification.

All values are truthy unless they are falsy. So we only have to know the falsy ones to know the truthy ones.

Falsy values (ToBoolean result is false):

  • false
  • undefined
  • null
  • '' - empty string
  • 0, -0 and 0n - zero
  • NaN (Not a Number)

So truthy examples are (ToBoolean result is true):

  • true
  • {}
  • "false"

In certain operations (like in if/else statements), JavaScript will automagically convert a value into true or false by using these truthy/falsy rules. This is type coercion. Read more about it in the MDN web docs.

An example:

const student = {
  answer: 'correct'
};

// student.answer is truthy, so we get true and the answer is verified.
if (student.answer) {
  verifyAnswer();
}

Let's take a closer look at Boolean() and !!.

Boolean()

Always use Boolean as a function. So do this:

const trueOrFalse = Boolean('yes'); // true

Do not do this!

const trueOrFalse = new Boolean('yes');

trueOrFalse now becomes a Boolean object, not a boolean value! And we know {} is not falsy, so new Boolean() is always truthy. This can lead to unexpected behaviour.

typeof new Boolean(false); // object - {...}
typeof Boolean(false); // boolean - false

if (new Boolean(false)) {
  // This will run! Because the Boolean {} is coerced to true.
}

if (Boolean(false)) {
  // This will not run! Which is probably what you want.
}

More on this in the MDN web docs about the Boolean object.

!!

The logical NOT operator: !, the exclamation mark, also called a "bang". It translates truthy values to false and falsy values to true. Get it?

Doing that twice translates truthy values to true and falsy values to false.

This is double negation. If a statement is true, then it is not the case that the statement is not true. Complicated, but just remember !! results in a boolean. true for truthy values, false for falsy values.

const value = 'hello';

// Step 1. First bang.
const step1 = !value; // step1 = false (NOT truthy = false)

// Step 2. Second bang.
const step2 = !step1; // step2 = true (NOT false = true) 

// Thus
console.log(step1, !value); // false
console.log(step2, !!value); // true

What do experts say?

The excellent Airbnb style guide prefers the double bang / !!.

// good
const hasAge = Boolean(age);

// best
const hasAge = !!age;

In chapter 4 of the book You don't know JS by Kyle Simpson both options are considered good.

const a = "42";

// bad (will fail!):
if (a == true) {
	// ..
}

// also bad (will fail!):
if (a === true) {
	// ..
}

// good enough (works implicitly):
if (a) {
	// ..
}

// better (works explicitly):
if (!!a) {
	// ..
}

// also great (works explicitly):
if (Boolean( a )) {
	// ..
}

Why is explicit conversion better than implicit conversion?

There are multiple reasons to prefer explicit over implicit conversion.

First, it's easier to see what's intended. Good code makes you assume less and understand more. By using Boolean() or !! it becomes clear that the ToBoolean conversion is intented.

It prevents unexpected results, for example with the || and && operators.

const isValid = 'yes' && 'yup'; // isValid becomes 'yup', not true as with for example PHP. 
const isValid = 'yes' || 'no'; // isValid becomes 'yes', not true.
const isValid = Boolean('yes' && 'yup'); // isValid becomes true! Probably what we want.
const isValid = Boolean('yes' || 'no'); // isValid becomes true!

The || and && operators result in one of the two variables, not necessarily a boolean. By using Boolean() we make that explicit, one thing less to think about!

And it's also possible with a bang bang 🔫 🔫.

!!('yes' && 'yup'); // results in true

Performance

I did a quick jsperf test. I consider both operations to be basic and thus "fast enough" for most use cases. Readability and clarity would be more important to me. Still it's interesting to see the results.

I always thought the double bang was the way to go in terms of performance. Although with a double bang you have to make two conversions (falsy/truthy -> boolean -> boolean). But maybe browsers have some optimizations built-in, for either way.

Safari, !! wins.

Firefox, a draw.

Chromium, Boolean() wins (slightly).

No clear winner. Check your usage share of webbrowsers. 🙃

Conclusion

So. !! or Boolean()?

Just pick one! 😁

Personally I prefer Boolean(). I like the way this says it all: "Give me a boolean". Most developers would understand this immediately, !! is less clear (but easy enough to remember).

In terms of performance it doens't really matter, but you can type !! quicker. A valid argument for the lazy ones.

And a bonus point for Boolean(), it's a function. So you can do stuff like this:

const answers = ['', 'correct', '', 'good'];
const completedAnswers = answers.filter(Boolean);

If you want to read more about types in JavaScript I can greatly recommend the first book of You Don't Know JS, Types & Grammar.

@YoonHan
Copy link

YoonHan commented Aug 30, 2024

What a nice inspection!
Thanks for your hard work :)

@rubenvillartkww
Copy link

This is a great explanation!! Thanks a lot!

@viniciusteixeiradias
Copy link

Good job! Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment