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