Optional chaining without ES11? - Safely Access - Javascript Tips & Tricks
As you know, every year EcmaScript releases a new version to improve JavaScript, these improvements have made our lives easier, and have allowed us to do things that we could not do with the language natively before, or that required many lines of code.
In this post we will talk a little bit about optional chaining (implemented in ES11/ES2020 version) instead of all the improvements introduced. For those who do not know, optional chaining is a functionality that allows us to safely access properties of objects in javascript, avoiding common errors such as "Can not read property foo of undefined".
Suppose we want to get the amount of apples from fruit objects has only bananas. Let's see what result we get with and without "optional chaining". I leave you an example
const fruits = {
bananas: {
quantity: 12
}
}
fruits.apples.quantity // ERROR: Cannot read property 'quantity' of undefined
// With optional chaining
fruits.apples?.quantity // undefined
As I mentioned earlier, this functionality was introduced in ES11, but what alternatives were there before for this? Let's see some of them 🚀
"Optional chaining" with OR operator
As we know, javascript parentheses are used to evaluate an expression, so for the previous example we can check if "apple" exists in the fruits object before accessing the next property.
To do that we can use the OR operator like this.(fruits.apples || {}).quantity // undefined
In this example, the operator will return the value of apples if it isn't falsy value, otherwise {}
In other words, we have (undefined || {}).quantity
literally, so it is safe to access "quantity" from an empty object and not from an undefined
value.
"Optional chaining" with AND operator
This is the most common option and perhaps the longest. Using the same example with the AND operator, it looks like this:fruits.apples && fruites.apples.quantity // undefined
Safely access to properties with default parameters
If we want to safely access the property of an object through a function parameter, we can use the previous alternatives or use the default parameter (implemented in ES6).
I leave you an example:
const fruits = {
bananas: {
quantity: 12
}
}
const getFruitQuantity = (fruit = {}) => {
return fruit.quantity
}
getFruitQuantity(fruits.apples) // undefined
Useful functions for more complex objects.
With some of these alternatives we can build a function that helps us access more complex object properties.
Using the fruits object:
const fruits = {
bananas: {
quantity: 12
}
}
I leave you some examples found on the net:get = function(obj, key) {
return key.split(".").reduce(function(o, x) {
return (typeof o == "undefined" || o === null) ? o : o[x];
}, obj);
}
/* Usage */
get(fruits, 'apples.quantity') // undefined
const getNestedObject = (nestedObj, pathArr) => {
return pathArr.reduce(
(obj, key) => (obj && obj[key] !== 'undefined' ? obj[key] : null),
nestedObj
);
};
/* Usage */
getNestedObject(fruits, ['apples', 'quantity']) // null
Is it just to access objects?
Throughout this post, I have only mentioned the properties of objects, so does it work for objects only?
The answer is NO. 🤓
We can use both the mentioned alternatives and the "optional chaining", to access elements of arrays or execute functions in a safe way. I leave you some examples:const someObject = null
// OR operator
((someObject || {}).someFunction || function(){} )() // undefined
// AND operator
typeof someObject === 'object' && typeof someObject.someFunction === 'function' && someObject.someFunction() // undefined
// Optional Chaining
someObject?.someFunction?.()
const someObject = null
const someArray = null
// OR operator
((someObject || {}).someArray || [])[0] // undefined
// AND operator
typeof someObject === 'object' && typeof someObject.someArray === 'object' && someObject.someArray[0] // undefined
// Optional Chaining
someObject?.someArray?.[0]
Conclusion
As you can see of the three ways learned, the longest is with the AND operator, but none is as short as the "optional chaining".
These types of errors are common and frequent, so it is necessary to know how to handle and avoid them.
If you find inconsistencies in the writing of this post or if on the contrary it is okay, please let me know in the comments section, English is not my native language but I try to express myself as best I can 🤗
Do you like microfrontends or have you heard of them? Be aware that I will talk about them soon
Comentar