completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

undefined

Learn where JavaScript creates undefined, how to tell it from missing names, and how defaults, JSON, void, and safe checks behave.

By the end, you can
  • 01
    Know where it comes fromPredict when a variable, a property, an index, an argument, a function result, a Map, or a search gives undefined.
  • 02
    Tell it apart from an errorExplain the difference between a variable that holds undefined, a property that is not there, and a name that was never created.
  • 03
    Choose safe checks and defaultsPick the right tool on purpose: === undefined, typeof, ??, ?., default values, and the JSON rules.

What undefined means

undefined is a value. JavaScript uses it to mean "nothing has been put here yet." It is also its own type. The typeof operator tells you the type of a value, as text. So typeof undefined gives the text "undefined".

Definition

undefined is the value you get when a place exists but nothing was put in it. The place can be a variable, a property, an argument, or the result of a function. It is a real value. It is not the same as a name that was never created.

Two empty variables and the value undefinedPop out in the code editor (opens in a new tab)JavaScript
let formField;var oldStyle;console.log(undefined);console.log(typeof undefined);console.log(formField);console.log(oldStyle);

Lines 1 and 2 create two variables, formField and oldStyle. Neither one gets a value. So lines 5 and 6 print undefined. Line 3 prints the value undefined itself. Line 4 is different. It prints the type, which is the text "undefined". The console shows the same word for both.

A const must get a value right awayPop out in the code editor (opens in a new tab)JavaScript
const needsValue;

let and the older var can start with no value. const cannot. A const must get its value on the same line. Without one, you get a SyntaxError: JavaScript refuses to run the code at all.

The hoisting lesson explains one more case. In classic scripts, a var reads as undefined even before the line that gives it a value.

Real-life analogyAn empty locker with your name on it

Picture a row of lockers. One locker has your name on it, but it is empty. That is like a variable whose value is undefined. Now picture asking for a locker number that is not on the wall at all. That is like reading a name that was never created. JavaScript throws a ReferenceError.

In real life: The locker is there, with your name on it
In JavaScript: A variable or property exists
In real life: Nobody has put a bag inside yet
In JavaScript: Its value is undefined
In real life: A locker number that is not on the wall
In JavaScript: A name that was never created

Where undefined comes from

STEP THROUGH

Most undefined values are not mistakes. JavaScript gives you undefined when nothing was:

  • put into a variable,
  • found at a property or an index,
  • passed in as an argument, or
  • returned from a function.

Below, you can step through these cases one at a time.

A missing argument starts as undefinedPop out in the code editor (opens in a new tab)JavaScript
function greet(name) {  console.log(name);}greet();

Line 1 makes a function, greet, with one parameter, name. A parameter is a variable that holds what the caller passes in. Line 4 calls greet but passes nothing. So on line 2, name is undefined. The function still runs. It just has no name to print.

Step through everyday ways to get undefined
Step 0 of 16Ready
Your turn: follow the blue line

Step through everyday ways to get undefined: empty variables, missing keys, array holes, strings, Maps, empty arrays, and searches that find nothing.

Running in
  1. script
Next: line 1
let oldCounter;const profile = { name: "Ada" };const tasks = ["learn"];const sparse = [1, , 3];const pantry = new Map([["tea", 2]]); console.log(draftTitle);console.log(oldCounter);console.log(profile.age);console.log(tasks[5]);console.log(sparse[1]);console.log("abc"[5]);console.log(tasks.at(-10));console.log(pantry.get("coffee"));console.log([].pop());console.log([1, 2].find((n) => n > 5));
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

The step-through shows each of these reads giving undefined:

  • Two variables that never got a value (lines 8 and 9).
  • A property the object does not have, profile.age (line 10).
  • An index past the end of an array, tasks[5] (line 11).
  • A hole in an array, sparse[1] (line 12). The next section explains holes.
  • An index past the end of a string, "abc"[5] (line 13).
  • tasks.at(-10) (line 14). With a negative number, at counts back from the end. Here it goes past the start.
  • A key that a Map does not have, pantry.get("coffee") (line 15). A Map is a list of keys and values, and get looks up one key.
  • [].pop() (line 16). pop removes the last item, but an empty array has none.
  • find with no match (line 17). find returns the first item that passes the test. Here, no item does.

Missing properties, indexes, and holes

Reading a property that an object does not have is safe. You get undefined. But when a value in the middle of a chain like user.address.city is missing, the next read fails.

Arrays can also have holes. A hole is an empty spot with no item at all. Reading a hole gives undefined too, but nothing is stored there.

Reading places that are not therePop out in the code editor (opens in a new tab)JavaScript
const user = { name: "Ada" };const scores = [10, 20];const sparse = [1, , 3]; console.log(user.age);console.log(scores[5]);console.log(sparse[1]);console.log(1 in sparse);console.log("abc"[5]);console.log(scores.at(-10));

Lines 5, 6, 7, 9, and 10 all print undefined. Line 7 reads the hole in sparse. Line 8 checks that spot with the in operator. in asks, "Is there an item at this index?" It prints false. So index 1 is a hole, not a stored value, even though reading it gives undefined.

Reading through a missing value throwsPop out in the code editor (opens in a new tab)JavaScript
const user = {};console.log(user.address.city);
Reading user.address.city. The user cart is empty. Reading user.address gives the value undefined. Trying to read city from undefined throws a TypeError.user.address.cityuserundefineduser.addressTypeErrorno .city to read
Line 2 does two reads in a row. First, user.address: the cart is there, but it has no address, so you get undefined. Then JavaScript tries to read .city from undefined. There is nothing to read from, so it throws a TypeError.

When a step might be missing, use optional chaining, written ?.. If the value on its left is undefined or null, it stops and gives undefined instead of throwing. For example, user?.address?.city gives undefined here, not a TypeError.

Use ?. and ?? for a city that is not therePop out in the code editor (opens in a new tab)JavaScript
const user = { profile: {} };console.log(user.profile?.city);console.log(user.profile?.city ?? "Unknown");

Line 2 reads city, which profile does not have, so it prints undefined. Line 3 adds ??. It gives the value on its right when the left side is undefined or null. So the missing city becomes the text "Unknown".

Arguments and return values

STEP THROUGH

A function's parameters are variables inside the function. If a call passes fewer arguments than there are parameters, the extra parameters start as undefined. A function that returns nothing also gives back undefined.

The step-through below uses default parameters. In name = "friend", the value after = is used when no argument comes in.

Call one function with fewer arguments, undefined, and null
Step 0 of 16Ready
Your turn: follow the blue line

Call the same function four ways: with an argument, with none, with undefined, and with null. Watch when the default is used.

Running in
  1. script
Next: line 5
function greet(name = "friend", punctuation = "!") {  return "Hello, " + name + punctuation;} console.log(greet());console.log(greet(undefined, "?"));console.log(greet(null));
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

A default is used only when the argument is missing or is undefined. Passing null is different. null is a real value that someone chose, so the default is not used. The later lesson Booleans, null & undefined compares null and undefined side by side.

Left: greet(undefined). The name box gets the default, "friend". Right: greet(null). The name box keeps null, and the default is not used.greet(undefined)"friend"namedefault usedgreet(null)nullnamedefault not used
Both calls use function greet(name = "friend"). When the argument is undefined, the default "friend" goes into the box. When the argument is null, null goes into the box, and the default is not used.
Function calls that give undefinedPop out in the code editor (opens in a new tab)JavaScript
function showArgument(value) {  console.log(value);}function noReturn() {  const status = "saved";}function bareReturn() {  return;} showArgument();console.log(noReturn());console.log(bareReturn());const printed = console.log("console.log prints first");console.log(printed);console.log([1, 2].forEach((n) => n * 2));console.log([1, 2].find((n) => n > 5));console.log(new Map().get("missing"));console.log([].pop());
  • Line 11 passes no argument, so value is undefined.
  • Line 12 calls a function that has no return.
  • Line 13 calls a function with an empty return;.
  • Lines 14 and 15 show a surprise. console.log prints its message, and then it returns undefined.
  • Line 16 is similar. forEach runs a function once for each item, for the work it does. It returns undefined.
  • Lines 17 to 19 are lookups that find nothing.
Printing a value is not the same as returning itPop out in the code editor (opens in a new tab)JavaScript
const result = console.log("saved");console.log(result);

Line 1 prints "saved" right away. Then it stores what console.log returned in result. Line 2 prints result. So the output is saved, then undefined.

undefined vs not defined

These two sound alike, but they mean different things:

  • undefined: the variable exists, and its value is undefined.
  • Not defined: JavaScript cannot find any variable with that name.
An empty variable and a name that was never createdPop out in the code editor (opens in a new tab)JavaScript
let declared;console.log(declared);console.log(typeof declared);console.log(typeof neverDeclared);

Line 2 reads declared. It exists, so it prints undefined. Line 3 prints its type, the text "undefined".

Line 4 uses typeof on neverDeclared, a name that was never created. typeof has a special rule for this. It gives the text "undefined" instead of throwing. So it is a safe way to check for a name that might not exist.

Reading a name that was never created throwsPop out in the code editor (opens in a new tab)JavaScript
console.log(neverDeclared);

Without typeof, reading neverDeclared throws a ReferenceError. That error means "there is no variable with this name."

Left: let declared; makes a box called declared that holds undefined, so reading it gives undefined. Right: neverDeclared has no box at all, so reading it throws a ReferenceError.let declared;undefineddeclaredreads undefinedneverDeclaredno boxwith this nameReferenceError
let declared; makes a box with nothing put in it yet, so reading it gives undefined. Nobody ever made a box called neverDeclared, so there is nothing to read, and JavaScript throws a ReferenceError.

Checking and defaults

Pick the check that fits your question:

  • Is this variable undefined? Use value === undefined. The === operator checks that two values are exactly the same.
  • Does this name exist at all? Use typeof name === "undefined".
  • Do you need a fallback value? Use ?? and ?.. They keep 0, false, and "" (the empty string) as real values.
A key can exist and still hold undefinedPop out in the code editor (opens in a new tab)JavaScript
const present = { key: undefined };const missing = {}; console.log("key" in present);console.log("key" in missing);console.log(Object.hasOwn(present, "key"));console.log(Object.hasOwn(missing, "key"));console.log(Object.keys(present).join(","));console.log(JSON.stringify(present));

Line 1 makes an object with a key, key, whose value is undefined. Line 2 makes an empty object. Reading key from either one gives undefined. To tell them apart, ask whether the key exists:

  • "key" in obj (lines 4 and 5).
  • Object.hasOwn(obj, "key") (lines 6 and 7).
  • Object.keys(obj), which lists the keys (line 8).

Line 9 shows that JSON leaves the key out. The JSON section below explains why.

Defaults are used only for undefinedPop out in the code editor (opens in a new tab)JavaScript
function greet(name = "friend") {  console.log("Hello, " + name);}greet(undefined);greet(null); const [first = "fallback", second = "backup"] = [undefined, null];const { label = "Untitled", count = 0 } = { count: undefined };console.log(first);console.log(second);console.log(label);console.log(count);

Lines 4 and 5 call greet with undefined, then with null. Only the first call uses the default.

Lines 7 and 8 use destructuring: pulling values out of an array or an object into variables. A default after = works the same way there:

  • first gets "fallback", because its value is undefined.
  • second keeps null.
  • label gets "Untitled", because the object has no label.
  • count gets 0, because the object's count is undefined.
Use ?? when 0 or an empty string is a real valuePop out in the code editor (opens in a new tab)JavaScript
const savedItems = 0;const nickname = "";console.log(savedItems ?? 3);console.log(savedItems || 3);console.log(nickname ?? "Guest");console.log(nickname || "Guest");

Lines 3 and 5 use ??. It keeps 0 and the empty string, because it only replaces null or undefined.

Lines 4 and 6 use || (OR). It replaces any falsy value. A falsy value is one that if treats as false, such as 0 and "". So || throws away the real 0 and gives 3.

void and the global undefined

The void operator runs the expression after it, throws away the result, and gives undefined.

JavaScript also has a global property named undefined that holds this value. Global means you can use it anywhere. You cannot change it, and you cannot delete it.

void, and the settings of the global undefinedPop out in the code editor (opens in a new tab)JavaScript
const descriptor = Object.getOwnPropertyDescriptor(globalThis, "undefined");console.log(descriptor.writable);console.log(descriptor.configurable);console.log(void 0);console.log(void "hello");
  • Line 1 asks JavaScript for the settings of the global undefined property.
  • Line 2 prints false: you cannot write a new value into it.
  • Line 3 prints false: you cannot delete it or change its settings.
  • Lines 4 and 5 show that void always gives undefined.

These settings have been in place since ES5, the 2009 version of JavaScript. Now see what happens when code tries to change the value.

Outside strict mode, the change is ignoredJavaScript
undefined = "changed";console.log(undefined);
In strict mode, the change throwsPop out in the code editor (opens in a new tab)JavaScript
"use strict";undefined = "changed";

Strict mode is a stricter way to run JavaScript. You turn it on with "use strict" at the top. Without it, line 1 of the first block quietly does nothing, so line 2 still prints undefined. With it, the same change throws a TypeError.

Inside a function, you could make your own variable named undefined. Never do that. It makes code confusing, and JavaScript already gives you the real value. To see how the engine stores undefined, read undefined inside the engine.

undefined in math, text, and JSON

undefined is falsy, so if treats it as false. Other operations have their own rules:

  • In math, it becomes NaN, which means "not a number".
  • In text, it becomes the word undefined.
  • In JSON, the result depends on where it is.
undefined in math, text, comparisons, and JSONPop out in the code editor (opens in a new tab)JavaScript
console.log(undefined + 1);console.log(`value: ${undefined}`);console.log(String(undefined));console.log(Number(undefined));console.log(undefined == null);console.log(undefined === null);console.log(JSON.stringify({ a: undefined }));console.log(JSON.stringify([undefined]));console.log(JSON.stringify(undefined));
  • Lines 1 and 4 give NaN.
  • Lines 2 and 3 give the text undefined.
  • Line 5 uses loose equality, ==. It counts null and undefined as equal, so it prints true.
  • Line 6 uses strict equality, ===. It does not count them as equal, so it prints false.
  • Lines 7 to 9 use JSON.stringify. It turns a value into JSON text. JSON is the text format web apps use to send data.
JSON.stringify with undefined. An object property { a: undefined } gives {}. An array [undefined] gives [null]. undefined on its own gives back undefined, not a string.you passyou get{ a: undefined }{}key left out[undefined][null]slot becomes nullundefinedundefinednot a string
JSON has no undefined, so JSON.stringify does one of three things. In an object, it leaves the key out. In an array, it writes null so the array keeps its length. On its own, it gives back undefined, not a string.

The last line is the surprise. JSON.stringify(undefined) does not give a string at all. It gives back the value undefined.

Try small programs

PLAYGROUND

Pick a small program from the list. Then compare three things: the value, its type, and what the console prints. Most programs give undefined. One throws on purpose, because a value in the middle of a chain is missing.

Playground: pick a small program
The program you pickedPop out in the code editor (opens in a new tab)JavaScript
let x;console.log(x);
Real resultundefined
Programlet x; x
Valueundefined
The console printsundefined

The variable exists, but nothing was put in it, so it holds undefined.

Try it yourself

let x; x gives undefined. Its type is undefined. The console prints: undefined. The variable exists, but nothing was put in it, so it holds undefined.

Each program is real JavaScript. The lesson's tests run every one, so the result shown here is what JavaScript really gives.

Sort the outcomes

SORTER

Some expressions look alike but give different results: undefined, null, an error, or something else. Sort each card by what JavaScript really does.

undefined, null, or an error?
  • ({}).x
  • null.x
  • neverDeclared
  • [].pop()
  • "abc"[5]
  • "abc".match(/z/)
  • JSON.parse("null")
  • typeof neverDeclared
  • new Map().get("k")
  • [1, 2].find((n) => n > 5)
  • (() => {})()
  • void "hi"
  • [1, , 3][1]
  • ({ a: null }).a
  • JSON.stringify(undefined)
  • ({})?.address?.city
Try it yourself
0 of 16 correct

Put each expression in the group for its real result.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Where you meet undefined in real code

In real projects, undefined often shows up in three places:

  • settings objects, where the caller leaves some settings out,
  • function parameters that the caller may skip, and
  • data from a server (an API) where a field is missing.

The safe way is to read with care, use a fallback only for undefined or null, and keep real values like 0.

A settings object and a missing fieldPop out in the code editor (opens in a new tab)JavaScript
function connect(options = {}) {  const retries = options.retries ?? 3;  return "retries: " + retries;} const apiUser = { profile: { name: "Ada" } };console.log(connect({ retries: 0 }));console.log(connect({}));console.log(apiUser.profile?.address?.city ?? "Unknown city");
  • Line 1 gives options a default, {}, an empty object. So a caller can leave out the whole settings object.
  • Line 2 uses ??. So on line 7, retries: 0 stays 0.
  • Line 8 passes no retries, so the fallback, 3, is used.
  • Line 9 reads a city that is not there and prints "Unknown city".

Keep these habits:

  • Write options = {} so callers may leave out the whole settings object.
  • Use ?? so 0 stays a real setting.
  • Use ?. before a field that may be missing.
  • When data should say "empty on purpose", expect null. The null lesson covers it.
Read a profile that has no phonePop out in the code editor (opens in a new tab)JavaScript
const response = { user: { name: "Asha" } };console.log(response.user?.name ?? "Guest");console.log(response.user?.phone ?? "No phone");

The response has a name but no phone. ?. makes the read safe, and ?? turns the undefined into the text "No phone".

Common misconceptions

  • "undefined means the variable does not exist." No. A variable that exists can hold undefined. Reading a name that was never created throws an error.
  • "A missing property and a missing value in the middle behave the same." No. obj.missing is safe and gives undefined. obj.missing.x throws a TypeError.
  • "Array holes store undefined." No. A hole is an empty spot with nothing stored. Reading it gives undefined, but index in array is false.
  • "Defaults replace null." No. Defaults are used only for undefined and for missing arguments or properties.
  • "JSON has an undefined value." No. JSON has null, but it has no undefined.

The table below compares four ways a value can be missing. Read each row from left to right: what you have, an example, what reading it gives, whether the key exists, and what JSON gives.

Four ways a value can be missing
What you haveExampleWhat does reading it give?Does the key exist?What does JSON.stringify give?
A variable with no valuelet x;Reading x gives undefined. typeof x gives "undefined".x is a variable, not a key, so there is no key to check.JSON.stringify({ x }) gives {}.
A property that is not thereconst obj = {}; obj.xReading obj.x gives undefined.No. "x" in obj is false.JSON.stringify(obj) gives {}.
A property that holds undefined{ x: undefined }Reading obj.x gives undefined.Yes. "x" in obj and Object.hasOwn(obj, "x") are both true.JSON leaves the key out.
A name that was never createdneverDeclaredReading it throws a ReferenceError. typeof neverDeclared safely gives "undefined".It is not a key, so in cannot check it.You cannot turn it into JSON, because you cannot read it.

Practice exercises

6 EXERCISES
Exercise 1 · Warm-upPredict three origins

Predict the three lines the console prints, in order.

Starter codePop out in the code editor (opens in a new tab)JavaScript
let x;
const obj = {};
console.log(x);
console.log(obj.missing);
console.log([1][1]);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upDefault or null?

    Predict what the two calls print.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    function label(value = "fallback") {
      return value;
    }
    console.log(label(undefined));
    console.log(label(null));

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticePresent or missing?

      Predict what the two key checks print.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const settings = { theme: undefined };
      console.log("theme" in settings);
      console.log("mode" in settings);

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeRead a missing city safely

        What exact city text prints?

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const user = { profile: {} };
        const city = user.profile?.address?.city ?? "Unknown";
        console.log(city);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · PracticeTurn undefined into JSON

          Predict the three lines the console prints.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          console.log(JSON.stringify({ a: undefined }));
          console.log(JSON.stringify([undefined]));
          console.log(JSON.stringify(undefined));

          Answer, then press Check. Spacing and letter case don’t matter.

            Exercise 6 · ChallengeCheck a name that may not exist

            Which operator makes this check safe, even though maybeName was never created?

            Starter codePop out in the code editor (opens in a new tab)JavaScript
            if (typeof maybeName === "undefined") {
              console.log("safe");
            }

            Answer, then press Check. Spacing and letter case don’t matter.

              Check your understanding

              8 QUESTIONS
              undefined quiz · 8 questionsScore: first tries count
              1. Question 1 of 8What does typeof undefined return?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                console.log(typeof undefined);

                Choose an answer to see the explanation.

              2. Question 2 of 8What does a let variable with no value print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                let draft;
                console.log(draft);

                Choose an answer to see the explanation.

              3. Question 3 of 8What happens here?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                const user = {};
                console.log(user.address.city);

                Choose an answer to see the explanation.

              4. Question 4 of 8Which check is safe for a name that might never have been created?

                Choose an answer to see the explanation.

              5. Question 5 of 8Which calls use the default parameter?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                function greet(name = "friend") {
                  console.log(name);
                }
                greet(undefined);
                greet(null);

                Choose an answer to see the explanation.

              6. Question 6 of 8What does void "hi" give?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                console.log(void "hi");

                Choose an answer to see the explanation.

              7. Question 7 of 8What do these comparisons print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                console.log(undefined == null);
                console.log(undefined === null);

                Choose an answer to see the explanation.

              8. Question 8 of 8What does JSON do with undefined?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                console.log(JSON.stringify({ a: undefined }));
                console.log(JSON.stringify([undefined]));
                console.log(JSON.stringify(undefined));

                Choose an answer to see the explanation.

              Key takeaways

              • undefined is a value, and also its own type. typeof undefined gives "undefined".
              • You get it when nothing was put into a place, found, passed in, or returned.
              • Reading a name that was never created throws a ReferenceError. typeof neverDeclared is the safe way to check.
              • Defaults are used for undefined, not for null.
              • Choose ?., ??, Object.hasOwn, and the JSON rules on purpose. Don't rely on if (value) alone.

              Final definition: undefined is JavaScript's built-in value, and type, for a place that exists but has nothing in it.

              Up next: null, the value you write yourself when you want to say "nothing here, on purpose."

              CompleteFrontend Clear concepts. Working examples.