Javascript Tricks
Tags: javascript, tricks, nullish
Published: 2020-09-05 02:12:44

# How to check null value and undefined to get a nested object's property?

##nullish and chain operators
```javascript
 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:

```javascript
  //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).

```javascript
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.
```javascript
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:
```javascript
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
```javascript
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.
```javascript
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.

```javascript
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)
> ```javascript
<div onclick="console.log('div')">Hello</div>
```
- Bind Callback (Medium Priority)
> ```javascript
div.onclick = () => console.log('div');
```
- Add/Remove Event Listener: Supports Multiple Callbacks associated with the same event.  Supports Event bubbling and capturing.
> ```javascript
div.addEventListener('click', callbackOne);
div.removeEventListener(callbackOne);
```
##Bubbling
```javascript
<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
```javascript
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:
```javascript
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.
```javascript
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.
```javascript
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 <p> 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
```javascript
// 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. 
```javascript
// 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);
  }
}
```