What Is the Optional Chaining Operator, and How Does It Work?

TLDR: Optional Chaining Operator is for objects, not properties?
https://www.w3schools.com/jS/js_2020.asp

" The Optional Chaining Operator returns undefined if an object is undefined or null (instead of throwing an error)."

/TLDR

I’ve found a quiz question pretty confusing but I thought I would discuss it here first before opening an Issue right away…

EDIT: Link to quiz:
https://www.freecodecamp.org/learn/full-stack-developer/lecture-working-with-objects/what-is-the-optional-chaining-operator-and-how-does-it-work

Here is the question:

What will be the output of the following code?

let car = {
    brand: "Toyota",
    model: "Corolla"
};

console.log(car?.color);

Toyota
Corolla
undefined
This will throw an error.

Here the question puts the ?. operator after the object name, which we have not seen in the video. In all of the examples, this operator comes after a property of the object. So already I’m not really sure what the result would be.

Since the operator is after the object name, and not the property I thought it might throw an error when it gets to the property which does not exist, but that’s incorrect:

Incorrect.
The optional chaining operator returns undefined if the property doesn’t exist.

Ok, fair enough but I needed to test it because the operator is before the object not the property.

let car = {
    brand: "Toyota",
    model: "Corolla"
};

console.log(car?.color);
>> undefined

:white_check_mark: Ok so it’s correct it does return undefined in this case. And if I remove the optional chaining operator?

let car = {
    brand: "Toyota",
    model: "Corolla"
};

console.log(car.color);
>> undefined

Ok, that’s strange! I thought it was the optional chaining operator that returns undefined and avoids throwing an error?

Maybe it has something to do with the property being last in the chain. How can I generate an error…

let car = {
    brand: "Toyota",
    model: "Corolla",
    color: {
      first: "white",
      second: "blue"
  }
};

console.log(car.colors.third);
>> TypeError: car.colors is undefined 

Ok! I have a TypeError thrown when this new object within the object does not exist. Can I supress it with ?. ?

console.log(car.colors?.third);
>> undefined

Success! What about the last node in the chain…

let car = {
    brand: "Toyota",
    model: "Corolla",
    color: {
      first: "white",
      second: "blue"
  }
};

console.log(car.color.third);
>> undefined

Simply returns undefined, with or without the ?.

So, the only way I’m able to generate an error and then suppress it with ?. is if I use it after an object name, the properties seem to make no difference.

So, the message here: “The optional chaining operator returns undefined if the property doesn’t exist.” seems to be wrong. A non-existant property seems to always return undefined.

I see this also corresponds to what w3 says:
" The Optional Chaining Operator returns undefined if an object is undefined or null (instead of throwing an error)." https://www.w3schools.com/jS/js_2020.asp

Example
const car = {type:"Fiat", model:"500", color:"white"};
let name = car?.name;

It’s about objects, not properties.

However, all the examples in the lesson are about properties:

console.log(user.profile?.address?.street); // "123 Main St"
console.log(user.profile?.phone?.number);   // undefined

Ok reading through the lesson again, it does show this. The first example the property doesn’t exist and returns undefined and it’s when the property in the object is ALSO an object, then it throws an error and you can use ?.

It’s a little more clear now. What threw me is that in the quiz it’s the first example where they use it on the first node in the chain, and it also returns undefined with or without the ?.

I’ll add that the W3 example returns undefined in either case as well.

const car = {type:"Fiat", model:"500", color:"white"};
let name = car?.name;
console.log(name)
>> undefined
let name = car.name;
console.log(name)
>> undefined

So even then the ?. makes no difference.

Tested this on codepen and w3’s editor. Maybe it has something to do with browser or enivronment versions?

So you’d think if the object doesn’t exist the ?. would supress the error and return undefined

const boats = {type:"Fiat", model:"500", color:"white"};
let name = car?.name;
console.log(name)
>> ReferenceError: car is not defined 

Nope, throws an error.

So ?. applies only to objects that are properties of other objects

try adding a let car; at the top, the error is not becouse it is not defined, it is because it is not declared, which is a thing that the optional chaining doesn’t deal with

let car;
const boats = {type:"Fiat", model:"500", color:"white"};
let name = car?.name;
console.log(name)
>> undefined

yes, it is a difference between strict mode and not strict mode, modern environments are usually in strict mode, undeclared variables error out in strict mode

like various other things that fail silently in not-strict-mode

can I suggest the MDN? it’s a bit more precise with things than that other site. It also mention this specific issue

1 Like

Thanks, that does help. Again, I think the focus is on the object, not on the property.

From the fCC lesson:

The optional chaining operator (?.) is a useful tool in JavaScript that lets you safely access object properties or call methods without worrying whether they exist. It’s like a safety net for working with objects that might have missing parts.

I would change the wording to:

t lets you safely access object properties or call methods without worrying whether the the object exists. It’s like a safety net for working with objects that might not be defined.

From MDN:

If the object accessed or function called using this operator is undefined or null, the expression short circuits and evaluates to undefined instead of throwing an error.

Just to say that this is about undefined objects, or properties of undefined objects, not about missing properties.

Back to the original Quiz question:

Here the ?. makes no difference (tested in fCC editor which is strict mode I believe?) it outputs undefined with or without it. But if I make the change you suggested:

let car;

let boats = {
    brand: "Toyota",
    model: "Corolla"
};

console.log(car?.color);

Now it returns undefined but generates the TypeError: car is undefined error without the ?.

Maybe the quiz question would make more sense like this?

A missing object property will just return undefined and not throw an error:

let car = {
    brand: "Toyota",
    model: "Corolla"
};

console.log(car.color);
>> undefined

So using ?. here makes no difference.

1 Like

it’s also about missing properties, it’s about anytime you may be accessing a property or method of undefined or null

From the last example, you would get an error from car.color.hue because car.color is undefined and you are trying to get a property of undefined

Other situation where it is useful:
document.querySelector('some element')?.getAttribute(...)
querySelector returns null if it doesn’t find an element, null.getAttribute() would get an error, but with the optional chaining the line collapses to undefined

Right, but this is because car.color is also an undefined object. Do we refer to them as both a property and an object when it’s inside another object? In any case, it behaves the same way as any undefined object in this case.

If it’s simply an undefined property (leaf node) it returns undefined without an error.

Actually, it says this explicitly in the lesson here:

By using the optional chaining operator, we are telling JavaScript to only continue with the operation if the object (or the value before the ?.) exists and is not null or undefined.

1 Like

The optional chaining operator returns undefined if the property doesn’t exist.

Wouldn’t you say this sentence is incorrect?

The property here is color and it doesn’t exist. However, without the ?. this will also output undefined.

The ?. will only return undefined if the car object is declared but is undefined.

From the lesson:

If the value before the ?. is null or undefined, JavaScript returns undefined rather than attempting to proceed with the operation and throwing an error.

?. works on the value before, which is an object, not the value following, which is a property.

From the MDN again:

The optional chaining (?.) operator accesses an object’s property or calls a function. If the object accessed or function called using this operator is undefined or null, the expression short circuits and evaluates to undefined instead of throwing an error.

“If the object accessed … using this operator is undefined or null…”

everything is an object in JavaScript, so it’s not wrong

I would say that the optional chaning is unncesessary in that question and the question maybe should be replaces

3 Likes

But does a rose by any other name smell as sweet?

Of course in this case we need to distinguish between objects and properties of objects. Of course color in car.color.hue is both a property and an object? That’s why I’ve been using “leaf node” sometimes to distinguish something at the end of the chain.

The optional chaining operator returns undefined if the property doesn’t exist.

This sentence refers to color from car?.color and it is wrong because the optional chaining operator isn’t returning undefined here because car exists and it is defined. This can be proven empirically because car.color also returns undefined.

that is explained not that well, yes
it’s not accessing a property that doesn’t exist the issue, it’s accessing a property of something that evaluates to undefined or null

car.color would give an error if car is undefined or null, then you can car?.color to avoid the error

if car exists but it doesn’t have a color property, it is not the place for optionla chaining

1 Like

I think it’s ok because you would use optional chaining if don’t know if the object is defined. Something could happen later in the code or during refactoring that could cause this and the ?. would catch it.

Examples are tough here because the program is so small nothing is unknown. Unless it’s an excerpt from an imaginary larger codebase.

Thanks so much for taking the time to discuss this with me! It’s helped a lot to understand.

I think the main point as well is that I finished this lesson confused about optional chaining. I thought it was used in case a property was missing, as implied in that quiz question.

I just wanted to improve the wording to help other people avoid that. I wanted to make sure I understood it properly first as well.

it’s great you are doing this! finding something confusing, making sure you understand it well, and then going back to improve the first source you had is a really great act of public service

1 Like