How to check null value and undefined to get a nested object's property?
nullish and chain operators
const product = { name: 'Coke', price: 10, provider: { name: 'Wailkk', address: 'Fake Street', state: { id: 1, name: 'Florida', country: { code: 'US', name: 'United States', }, }, orders: null, fPrice: (x) => 100, }, }; //Old way const providerCountry = product.provider ? product.provider.name ? product.provider.name : null : null; //Nullish Coalsencing Operator Way //If the value is null then this option it will not works. const _providerCountry = product.provider.name ?? undefined; //Not work if the value is null const providerOrders = product.provider.orders ?? 1; // Should be null. [Error] // Nullish not defined. const providerNotDefined = product.provider.notDefined ?? null; //Trick: chaining Operator const providerAddress = product?.provider?.address; //It works with Dynamic properties. const propertyName = 'price'; const productPrice = product?.[propertyName]?.explore;
Chain Operator Way
If a property doesn't exist or value is undefined then will returns undefined, keeping your code clean. If a property doesn't exist undefined will be returned. Let's see how this operator looks with the same example object:
//Trick: chaining Operator const providerAddress = product?.provider?.address; //It works with Dynamic properties. const propertyName = 'price'; const productPrice = product?.[propertyName]?.explore; //Works with Functions too. const productProviderPrice = product?.provider?.fPrice?.('x'); //Result: 100; const _productProviderPrice = product?.provider?.fPricex?.('x'); //Result: undefined
NOT Compatible with: Internet Explorer, Firefox for Android, Opera for Android, and Samsung Internet Browser.
IIFE: Immediately-Invoked Function Expression
It's a function invoked immediately after it is defined (as the name says).
let hi = (() => { return 'Hello Dear World'; })(); //Define function and parenthesis before the semicolon. console.log(hi); // Result = 'Hello Dear World'
Function Closures
Combination of functions stacked or bundled together with access over outer layers or outer function's scope.
const functionLevelOne = () => { let day = 23; const functionLevelTwo = () => { day += 1; return day; } return functionLevelTwo; } console.log(functionLevelOne()); // Result: 24; // It's calling the return function on level one.
When to use spread operators?
Merge two arrays using spreads could impact on performance if it's a repetitive call. And if we call a function passing arguments like spread and that call is frequently. Use ...spread only when it's not a repetitive call or for a function's call but not as argument spread definition.
I will keep adding and updating tricks to this article frequently.
Find and Filtering
- Find a record for key value:
let colors = [ { id: 0, color: 'Red' }, { id: 1, color: 'Green' }, { id: 2, color: 'Blue' } ]; let greenColor = colors.find(color => color.color === 'Green');
Filter Records by id value
let users = [ { id: 0, name: 'John Smith' }, { id: 1, name: 'Mary Smith' }, { id: 2, name: 'Jane Foster' } ]; let filteredData = data.filter(path => path.includes('Smith'));
Returns the name of users with the last name 'Smith'.
Iterations
Iterate between key,values for an object.
let myObject = { one: 1, two: 2, three: 3 }; Object.keys(myObject).forEach((key, value) => { //...do something console.log(key, value); });
Event Loop Essentials.
A Task queue is used by Javascript. Javascript tasks have the highest priority. Micro Tasks like promises have the second priority position; third place for Macro Tasks executed before (requestAnimationFrame) or after (setTimeout) to render.
console.log(1); Promise.resolve().then(() => console.log(2)); setTimeout(() => console.log(3), 100); console.log(4); // 1 -> 4 -> 2 -> 3
There are three ways to add your callback function(s) to the DOM element as the event callback.
-
InLine (Higher Priority)
<div onclick="console.log('div')">Hello</div>
-
Bind Callback (Medium Priority)
div.onclick = () => console.log('div');
-
Add/Remove Event Listener: Supports Multiple Callbacks associated with the same event. Supports Event bubbling and capturing.
div.addEventListener('click', callbackOne); div.removeEventListener(callbackOne);
Bubbling
<div onclick="console.log('div')"> <p onclick="console.log('p')"> <span onclick="console.log('span')"> </span> </p> </div> //span → p → div
Bubbling: The innermost element → the second innermost element → … → the outermost element
Capturing: The outermost element → the second outermost element → … → the innermost element
Capturing is triggered earlier than bubbling
div.addEventListener('click', () => console.log('div')); p.addEventListener('click', () => console.log('p'), { capture: true }); span.addEventListener('click', () => console.log('span')); //Result: p → span → div
div and span use bubbling, and p uses capturing.
Event Delegation
If you have a loop function with multiple callbacks that will affects the performance:
const ul = document.getElementById('myUL'); for (let i = 0; i < 100; i += 1) { const li = document.createElement('li'); li.textContent = `li-${i}`; li.id = `li-${i}`; li.addEventListener('click', e => console.log(e.target.id)); ul.appendChild(li); }
Delegate one callback for all.
const ul = document.getElementById('myUL'); for (let i = 0; i < 100; i += 1) { const li = document.createElement('li'); li.textContent = `li-${i}`; li.id = `li-${i}`; ul.appendChild(li); } ul.addEventListener('click', e => console.log(e.target.id));
Event Propagation
Stop propagation makes a halt to the propagation used by bubbling or capturing.
div.addEventListener('click', () => console.log('div'), true); p.addEventListener('click', e => { e.stopPropagation(); console.log('p'); }); span.addEventListener('click', () => console.log('span'), true);
When user clicks
only will be logged 'p'.
XMLHttpRequest
Oldest fetch data in an asynchronous way
const oReq = new XMLHttpRequest(); oReq.open('GET', 'https://jsonplaceholder.typicode.com/todos/1'); oReq.send(); oReq.addEventListener('load', function () { console.log(this.responeText); });
Fetch
New way with more options than XMLHttpRequest, returns a promise
// Promise fetch(url) .then(res => res.json()) .then(data => console.log(data)); // async & await const res = await fetch(url); const data = await res.json(); console.log(data);
Axios
It takes the best of XMLHttpRequest and fetch.
// Promise axios.get('/user?ID=12345') .then(function (response) { // handle success console.log(response); }) .catch(function (error) { // handle error console.log(error); }) .finally(function () { // always executed }); // async & await async function getUser() { try { const response = await axios.get('/user?ID=12345'); console.log(response); } catch (error) { console.error(error); } }
Top comments (1)
Your "Function Closures" example returns the
functionLevelTwo
function, not 24