Added "Cannot read property "abc" of null/undefined."

This commit is contained in:
Lê Duy Quang
2021-02-25 04:21:57 -05:00
committed by Jean-Philippe Sirois
parent 607f8f8941
commit ac1ed508f7
@@ -0,0 +1,193 @@
---
authors:
- "leduyquang753#3761"
created_at: "2021/01/13"
title: Cannot read property "abc" of null/undefined
---
When running JavaScript code, a very common error that occurs is:
```none
console.log(someRandomThing.abc)
^
TypeError: Cannot read property "abc" of undefined
```
This is a very basic error, yet people who are new to JavaScript (and maybe
programming) often either gloss over or misunderstand the problem being
presented in their code, and come to _The programmer's hangout_ to seek an
explanation.
## Causes
### Direct cause
When the JavaScript engine complains about "Cannot read property `abc` of
`null`/`undefined`", it means that the thing whose property `abc` is being
retrieved is either `null` or `undefined`.
```js
$ node
> let someRandomThing;
undefined
> console.log(someRandomThing.abc);
// ---- Owner ----|Property
Uncaught TypeError: Cannot read property 'abc' of undefined
```
The most important thing to note here is it's the "_owner_" that is being
`null`/`undefined`. A common mistake is to interpret the error message as that
the "property" is `null`/`undefined` instead.
### Possible behind causes
For a variable to come up containing `null` or `undefined` (most commonly
`undefined`) so that the "Cannot read property" error can arise later, the code
must have done something wrong beforehand. This section lists some common
bugs and mistakes.
#### `undefined` from nonexistent object property
By default, when accessing an object's property in JavaScript, if the object in
question doesn't have such property, it will return `undefined` as the default.
This applies to nonexistent array indices as well.
```js
> let keyMapping = {
moveUp: "KeyW",
moveDown: "KeyS",
moveLeft: "KeyA",
moveRight: "KeyD"
};
undefined
> keyMapping.mvoeDown
// ^^ Typo, oops. The object doesn't have key "mvoeDown".
undefined
```
```js
> let randomNumbers = [16, 57, 3];
// Index: 0 1 2
undefined
> randomNumbers[3] // ! The array does not have index 3.
undefined
```
#### `null` from failed queries
Some functions, for example `getElementById` from the browser API, returns
`null` if the function failed to find any result matching what is requested.
If left unchecked and the returned value is used in other places, the "Cannot
read property" might arise.
```html
<!DOCTYPE html>
<html>
<body>
<p id=paragraph-1>Welcome to <i>The programmer's hangout</i>.</p>
<p id=paragraph-2>
This is the place for programmers of any skill level to, well, hangout
with other fellow programmers. Whether you have just written 5 lines of
code or been a code nerd for 15 years, you are always welcome!
</p>
<script>
let element = document.getElementById("paragraph-3");
// The one writing this might think this will add another paragraph to
// the page, which is not how it works.
// The browser, failing to find any element with ID "paragraph-3" from
// the page, returns null.
element.innerText = "When joining, make sure you read the rules.";
</script>
</body>
</html>
```
```none
Uncaught TypeError: Cannot set property "innerText" of null
at tph-welcome.html:16
```
#### `undefined` from uninitialized variables
When declaring a variable without an initializer, JavaScript defaults the value
of the variable to `undefined`. If nothing else is assigned to it later, the
error will show up.
```js
> let payload; // Defaults to undefined.
undefined
> let testValue = 6;
undefined
> if (testValue > 10) payload = { id: 167503, message: "Welcome to TPH." };
// As the condition does not satisfy, "payload" doesn't get assigned
// and remains undefined.
undefined
> console.log(payload.message)
Uncaught TypeError: Cannot read property 'message' of undefined
```
## Fixing
The way to fix the "Cannot read property `abc` of `null`/`undefined`" is of
course, to make sure what is being retrieved properties from is not either
`null` or `undefined`. Based on the reason behind the error, the programmer
determines how the issue shall be fixed.
#### Make sure a property exists
Through either checking or reading the documentation for the correct property,
one can make sure what is in their hands isn't JavaScript's default
`undefined`.
```js
async function onCommand(channel, arguments) {
// Assuming the command is not empty and
// there is always the first argument.
let commandName = arguments[0];
switch (commandName) {
// ...
case "getUser":
if (arguments.length < 2)
throw "Usage: /getUser <username>";
// It is guaranteed now that "arguments" has at least 2 elements
// and thus there is an index 1.
let username = arguments[1];
let user = await botClient.fetchUser(username);
channel.send(JSON.stringify(user);
break;
// ...
}
}
```
#### Handle a failed query
If a query for something fails and returns `null`, the programmer needs to make
sure that situation is handled properly.
```js
async function getUserID(username) {
// Assuming "username" is guaranteed to be a string.
let user = await botClient.fetchUser(username);
if (user == null) throw "There is no user with that name.";
// It is guaranteed now that "user" isn't null.
return user.id;
}
```
#### Make sure a variable contains an actual value
By either initializing the variable or guaranteeing the variable will
ultimately receive a value, the error won't be able to occur.
```js
let payload;
let rolledValue = Math.random();
if (rolledValue > 0.5)
payload = { id: 169323, message: "Welcome to TPH." };
else
payload = { id: 173205, message: "TPH has been waiting for you." };
// In either case, "payload" is guaranteed to be assigned an actual value.
botClient.sendMessage(serverJoiner, payload.message);
```