Reading a missing key
In JavaScript, an object used as a dictionary maps keys to values. Reading a key that is not there does not stop the program. It just gives undefined:
const pets = {"Rex": "dog", "Tom": "cat", "Polly": "parrot"};
console.log(pets["Zed"]);
undefined
That undefined can travel a long way before something breaks. So check whether a key exists before you rely on its value.
The in operator
Write key in obj to ask whether the object has that key. The answer is true or false, so it fits in an if:
const capitals = {"France": "Paris", "Japan": "Tokyo"};
if ("Japan" in capitals) {
console.log(capitals["Japan"]);
}
if (!("Spain" in capitals)) {
console.log("No Spain");
}
Tokyo
No Spain
Inside the first if, reading the key is safe, because the check already said it exists.
Traps
The parentheses in the not-check
For the opposite, put ! before the whole check, wrapped in parentheses. Without them, ! applies to the text alone. The expression !"Spain" in capitals turns "Spain" into false first and then asks whether a key named "false" exists, so the result is false unless the object happens to have a key named "false".
Do not test the value
It is tempting to write if (capitals["Spain"]). That mixes up "no key" with "a value that counts as false". With const e = {"a": "", "b": 0}, the value e["a"] is an empty string and e["b"] is 0. Both act as false in an if, yet both keys exist: "a" in e and "b" in e are true.
A value is not a key
The operator in looks only at the keys. "Paris" in capitals is false, because "Paris" is a value. Keys must also match exactly, upper and lower case too: "japan" in capitals is false.
Names every object already has
Plain objects inherit a few names, so "toString" in {} is true even though you never added it. For ordinary keys such as pet names this does not matter. When the keys can be anything, Object.hasOwn(obj, key) checks only the object's own keys.
When to check first
Check before you read whenever a key might be missing and the program would go wrong with undefined. Typical cases are data typed by a person, data from outside the program, and counters that have not started yet. If you are sure the key is there, because you just put it there, the check adds nothing. The skill is deciding which situation you are in, and writing the check in the places where a missing key is possible.
The check also gives you a choice. With the answer in hand you can print a friendly message for the missing case, as the "No Spain" line does, instead of letting undefined flow into the rest of the program.
The lesson's task
The object pets maps each pet's name to its kind. First check whether "Tom" is a key, and if so log Tom is a followed by Tom's kind. Then check that "cat" is not a key, with ! and in, and if so log cat is not a key. The word "cat" is in pets, but only as a value: it is Tom's kind.
const pets = {"Rex": "dog", "Tom": "cat", "Polly": "parrot"};
if ("Tom" in pets) {
console.log("Tom is a " + pets["Tom"]);
}
if (!("cat" in pets)) {
console.log("cat is not a key");
}
Tom is a cat
cat is not a key
The first check passes, so the first line prints. The second check asks about the key "cat", which does not exist, so "cat" in pets is false, the ! makes it true, and the second line prints.
Key takeaways
key in objistruewhen the object has that key, andfalsewhen it does not.- Write the not-check as
!(key in obj), with parentheses. inlooks at keys only, never at values, and matching is exact.
