What the not operator does
The logical NOT operator, written !, flips a boolean. If the value after it is true, the result is false, and the other way round. It goes in front of the value, which is why it is called a unary (one-operand) operator. Use it when you want a condition to mean "this is not the case": if it is not sunny, if the list does not contain the item, if the name is empty.
console.log(!true); // false
console.log(!false); // true
console.log(!(7 <= 10)); // false, because 7 <= 10 is true
console.log(!(12 != 12)); // true, because 12 != 12 is false
When the operand is a comparison or any longer expression, wrap it in parentheses. !(7 <= 10) negates the whole comparison. Without the parentheses, ! would apply only to the 7.
Using ! in an if statement
The most common use is to run code when a boolean variable is false. Reading if (!hungry) as "if not hungry" keeps the code close to plain English:
let hungry = true;
if (!hungry) {
console.log("I can wait a little longer");
} else {
console.log("I need food!");
}
Here !hungry is false, so the else branch runs and the output is I need food!.
! works on any value, not only booleans
JavaScript first converts the operand to a boolean, then flips it. Eight values convert to false and are called falsy: false, 0, -0, 0n (a zero BigInt), the empty string "", null, undefined and NaN. Everything else is truthy, including "0", "false", [] and {}.
console.log(!0); // true
console.log(!""); // true
console.log(!null); // true
console.log(!undefined); // true
console.log(!NaN); // true
console.log(!"hi"); // false
console.log(![]); // false
console.log(!{}); // false
console.log(!"0"); // false
This makes ! handy for checking that something is missing or empty:
const user = {};
if (!user.email) {
console.log("no email");
}
Reading a property that doesn't exist gives undefined, which is falsy, so the message prints. Be careful when 0 or an empty string is a valid value, such as a score of 0: !score is also true for it, and you may need score === undefined instead.
Double negation: !!
Writing ! twice converts any value to its boolean equivalent: the first ! flips it into a boolean, the second flips it back. !!"hi" is true, !!0 is false and !![] is true. It does the same as Boolean(value), which is often easier to read. !! is not a separate operator; it is just two ! in a row.
Toggling a flag
Assigning the negation back to the variable switches it between two states:
let on = false;
on = !on;
console.log(on); // true
on = !on;
console.log(on); // false
Not equal and "not in" checks
Many searches for "not" in JavaScript are really about one of these:
- Not equal:
!=and!==are comparison operators that contain a!.5 != "5"isfalse, because!=converts types before comparing.5 !== "5"istrue, because!==does not convert. As with===, prefer!==. You can also write!(a === b). - Not in an array:
!arr.includes(4)istruewhenarrdoes not contain 4. For[1, 2, 3],!arr.includes(2)isfalse. - Not a key of an object:
!("b" in obj)istruewhenobjhas no key"b". The parentheses matter:!"b" in objwould apply the!to"b"first, givingfalse in obj, which looks for the key"false". Note thatinalso finds inherited properties.
Combining ! with && and ||
The ! operator binds tighter than && and ||, and tighter than comparisons such as ===. So !a && b means (!a) && b, not !(a && b). Add parentheses to say which one you mean:
let a = true, b = false;
console.log(!a && b); // false: (!a) && b
console.log(!(a && b)); // true: not (a and b)
A negated group can be rewritten with De Morgan's laws: !(a && b) equals !a || !b, and !(a || b) equals !a && !b. With a = true and b = false, !(a && b) and !a || !b are both true, and !(a || b) and !a && !b are both false. Use whichever form reads better.
Common mistakes
- Leaving out parentheses around a comparison. With
x = 3,!x === 5negatesxfirst and comparesfalseto 5, which givesfalse. What you meant,!(x === 5), givestrue. Better still, writex !== 5. - Treating every falsy value as "missing".
!0and!""aretrue. If 0 or an empty string is a valid value, compare toundefinedornulldirectly. - Double negatives that hide the meaning.
if (!isNotReady)is hard to read. Name flags positively, such asisReady, and negate when you need to. - Using
!whereelsewould do.if (a) { ... } if (!a) { ... }is a long way of writingif (a) { ... } else { ... }.
The lesson's exercise
The code starts with a variable isSunny set to true. The task has two steps.
- Print "Learning to code" when it is not sunny. Write an
ifwhose condition is!isSunny, and callconsole.log("Learning to code")inside it. - Print "Going to the beach" otherwise. Add an
elsebranch on the same line as the closing brace of theif, and print the second message. Theelseruns when!isSunnyisfalse, which means it is sunny.
let isSunny = true;
if (!isSunny) {
console.log("Learning to code");
} else {
console.log("Going to the beach");
}
Because isSunny is true, !isSunny is false, and the output is Going to the beach. Change the first line to let isSunny = false; and the output becomes Learning to code.
Key takeaways
!turnstrueintofalseandfalseintotrue.- On other values it converts to a boolean first:
0,"",null,undefinedandNaNbecometruewhen negated, and most other values becomefalse. - Put parentheses around anything longer than a single value:
!(a === b). !!valueconverts a value to a boolean, and!==is the safe "not equal".
