JavaScript Other Topics
Shallow and Deep copy
Shallow Copy Deep Copy
A deep copy means that all of the values of the A shallow copy means that certain (sub-)values
new variable are copied and disconnected from are still connected to the original variable.
the original variable.
Object.assign() is example of shallow copy JSON.parse(JSON.stringify(object)), Lodash
cloneDeep() are examples of deep copy
Shallow Copy Examples
let obj1 = {
'firstName': 'Piyali',
'lastName': 'Das'
};
let obj2 = obj1;
obj2.firstName = 'Soma';
console.log(obj2); // {firstName: "Soma", lastName: "Das"}
console.log(obj1); // {firstName: "Soma", lastName: "Das"}
When you are using assignment operator(=) to copy the value, it will reference the same object with
original one in the memory. So obj1 and obj2 will act like same objects. Any changes in obj2 will reflect
in obj1.
let obj1 = {
'firstName': 'Piyali',
'lastName': 'Das'
};
let obj2 = Object.assign({}, obj1);
console.log(obj2); // {firstName: "Soma", lastName: "Das"}
console.log(obj1); // {firstName: "Piyali", lastName: "Das"}
Object.assign() can create deep copy when only have primitives values.
let obj1 = {
'firstName': 'Piyali',
'lastName': 'Das',
'address': {
'city': 'Kolkata',
'state': 'West Bengal'
}
};
let obj2 = obj1;
obj2.address.city = 'South 24 parganas';
obj2.firstName = 'Soma';
console.log(obj2);
1. {firstName: "Soma", lastName: "Das", address: {…}}
1. address: {city: "South 24 parganas", state: "West Bengal"}
2. firstName: "Soma"
3. lastName: "Das"
4. __proto__: Object
console.log(obj2);
1. {firstName: "Piyali", lastName: "Das", address: {…}}
1. address: {city: "South 24 parganas", state: "West Bengal"}
2. firstName: "Piyali"
3. lastName: "Das"
4. __proto__: Object
Now address is generating shallow copy where firstName and lastName are generating deep copy. The
reason is that the address is reference value while both firstName and lastName are primitive values.
Both obj1 and obj2 references different objects but these objects reference the same address objects.
let obj1 = {
'firstName': 'Piyali',
'lastName': 'Das',
'address': {
'city': 'Kolkata',
'state': 'West Bengal'
}
};
let obj2 = {...obj1};
obj2.address.city = 'South 24 parganas';
obj2.firstName = 'Soma';
console.log(obj2);
2. {firstName: "Soma", lastName: "Das", address: {…}}
1. address: {city: "South 24 parganas", state: "West Bengal"}
2. firstName: "Soma"
3. lastName: "Das"
4. __proto__: Object
console.log(obj2);
2. {firstName: "Piyali", lastName: "Das", address: {…}}
1. address: {city: "South 24 parganas", state: "West Bengal"}
2. firstName: "Piyali"
3. lastName: "Das"
4. __proto__: Object
Spread operator is doing same thing like Object.assign(). Spread operator can create deep copies only
for primitive values.
Deep Copy examples
let obj1 = {
'firstName': 'Piyali',
'lastName': 'Das',
'address': {
'city': 'Kolkata',
'state': 'West Bengal'
}
};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj2.address.city = 'South 24 parganas';
obj2.firstName = 'Soma';
console.log(obj2);
3. {firstName: "Soma", lastName: "Das", address: {…}}
1. address: {city: "South 24 parganas", state: "West Bengal"}
2. firstName: "Soma"
3. lastName: "Das"
4. __proto__: Object
console.log(obj2);
3. {firstName: "Piyali", lastName: "Das", address: {…}}
1. address: {city: "Kolkata", state: "West Bengal"}
2. firstName: "Piyali"
3. lastName: "Das"
4. __proto__: Object
JSON.parse(JSON.stringify(object)) creates deep copy. Any changes in obj2 will not change the values of
obj1.
Lodash | _.cloneDeep() Method is the best choice for deep clone copy.
slice vs splice
Slice Splice
Doesn't modify the original array(immutable) Modifies the original array(mutable)
Returns the subset of original array Returns the deleted elements as array
Used to pick the elements from array Used to insert or delete elements to/from array
== vs === operators
0 == false // true
0 === false // false
1 == "1" // true
1 === "1" // false
null == undefined // true
null === undefined // false
'0' == false // true
'0' === false // false
[]==[] or []===[] //false, refer different objects in memory
{}=={} or {}==={} //false, refer different objects in memory
Temporal Dead Zone
the term to describe the state where variables are un-reachable. The Temporal Dead Zone is a behavior
in JavaScript that occurs when declaring a variable with the let and const keywords, but not with var. In
ECMAScript 6, accessing a let or const variable before its declaration (within its scope) causes a
Reference Error. The time span when that happens, between the creation of a variable’s binding and its
declaration, is called the temporal dead zone.
function somemethod() {
console.log(counter1); // undefined
console.log(counter2); // ReferenceError
var counter1 = 1;
let counter2 = 2;
}
web storage
Web storage is an API that provides a mechanism by which browsers can store key/value pairs locally
within the user's browser, in a much more intuitive fashion than using cookies. The web storage
provides two mechanisms for storing data on the client.
i. Local storage: It stores data for current origin with no expiration date.
ii. Session storage: It stores data for one session and the data is lost when the browser tab is
closed.
Cookie
A cookie is a piece of data that is stored on your computer to be accessed by your browser. Cookies are
saved as key/value pairs. For example, you can create a cookie named username as below,
document.cookie = "username=John";
Need a Cookie
Cookies are used to remember information about the user profile(such as username). It basically
involves two steps,
iii. When a user visits a web page, the user profile can be stored in a cookie.
iv. Next time the user visits the page, the cookie remembers the user profile.
Options in a cookie
There are few below options available for a cookie,
By default, the cookie is deleted when the browser is closed but you can change this behavior by setting
expiry date (in UTC time).
document.cookie = "username=John; expires=Sat, 8 Jun 2019 12:00:00 UTC";
By default, the cookie belongs to a current page. But you can tell the browser what path the cookie
belongs to using a path parameter.
document.cookie = "username=John; path=/services";
Delete a cookie
You can delete a cookie by setting the expiry date as a passed date. You don't need to specify a cookie
value in this case. For example, you can delete a username cookie in the current page as below.
document.cookie = "username=; expires=Fri, 07 Jun 2019 00:00:00 UTC; path=/;";
Note: You should define the cookie path option to ensure that you delete the right cookie. Some
browsers doesn't allow to delete a cookie unless you specify a path parameter.
Differences between cookie, local storage, and session storage
Feature Cookie Local storage Session storage
Accessed on client or server Both server-side & client-side client-side client-side only
side only
Lifetime As configured using Expires until deleted until tab is
option closed
SSL support Supported Not supported Not supported
Maximum data size 4KB 5 MB 5MB
callback hell
Callback Hell is an anti-pattern with multiple nested callbacks which makes code hard to read and debug
when dealing with asynchronous logic. The callback hell looks like below,
async1(function(){
async2(function(){
async3(function(){
async4(function(){
....
});
});
});
});
server-sent events
Server-sent events (SSE) is a server push technology enabling a browser to receive automatic updates
from a server via HTTP connection without resorting to polling. These are a one-way communications
channel - events flow from server to client only. This has been used in Facebook/Twitter updates, stock
price updates, news feeds etc.
You can perform browser support for server-sent events before using it as below,
if(typeof(EventSource) !== "undefined") {
// Server-sent events supported. Let's have some code here!
} else {
// No server-sent events supported
}
<!DOCTYPE html>
<html>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("https://www.w3schools.com/html/demo_sse.php");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent
events...";
}
</script>
</body>
</html>
Getting server updates
The server time is: Wed, 07 Jul 2021 11:01:10 +0000
The server time is: Wed, 07 Jul 2021 11:01:13 +0000
The server time is: Wed, 07 Jul 2021 11:01:17 +0000
The server time is: Wed, 07 Jul 2021 11:01:20 +0000
The server time is: Wed, 07 Jul 2021 11:01:23 +0000
Below is the list of events available for server sent events
Event Description
onopen It is used when a connection to the server is opened
onmessage This event is used when a message is received
onerror It happens when an error occurs
promise chaining
The process of executing a sequence of asynchronous tasks one after another using promises is known
as Promise chaining.
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000);
}).then(function(result) {
console.log(result); // 1
return result * 2;
}).then(function(result) {
console.log(result); // 2
return result * 3;
}).then(function(result) {
console.log(result); // 6
return result * 4;
});
promise.all
Promise.all is a promise that takes an array of promises as an input (an iterable), and it gets resolved
when all the promises get resolved or any one of them gets rejected.
let urls = [
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2',
'https://jsonplaceholder.typicode.com/posts/3'
];
// map every url to the promise of the fetch
let requests = urls.map(url => fetch(url));
// Promise.all waits until all jobs are resolved
Promise.all(requests)
.then(responses => responses.forEach(response => {
console.log(response.url + response.status + response.data);
));
Promise.race()
Promise.race() method will return the promise instance which is firstly resolved or rejected.
let urls = [
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/users',
'https://jsonplaceholder.typicode.com/posts'
];
// map every url to the promise of the fetch
let requests = urls.map(url => fetch(url));
Promise.race(requests).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster
});
Promise {<pending>}
Response {type: "basic", url: "https://jsonplaceholder.typicode.com/users", redirected: false, status:
200, ok: true, …}
Code execute in console
Check API speed from network tab
Users API fetch timing is less than others 17 ms. So, Promise.race() return 2nd promise (Users).
Promise.allSettled()
The Promise.allSettled() method returns a promise that resolves after all of the given promises have
either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.
let urls = [
'https://jsonplaceholder.typicode.com/comments',
'https://jsonplaceholder.typicode.com/users',
'https://jsonplaceholder.typicode.com/posts'
];
// map every url to the promise of the fetch
let requests = urls.map(url => fetch(url));
Promise.allSettled(requests).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster
});
(3) [{…}, {…}, {…}]
Promise.allSettled() vs Promise.all()
Promise.all() will reject as soon as one of the Promises in the array rejects. Promise. allSettled() will
never reject, it will resolve once all Promises in the array have either rejected or resolved.
Fetch
The Fetch API provides a JavaScript interface for accessing and manipulating parts of the HTTP pipeline,
such as requests and responses.
A basic fetch request is really simple to set up. Have a look at the following code:
fetch('http://example.com/movies.json')
.then(response => response.json())
.then(data => console.log(data));
Strict Mode
Strict Mode is a new feature in ECMAScript 5 that allows you to place a program, or a function, in a
“strict” operating context. This way it prevents certain actions from being taken and throws more
exceptions. The literal expression "use strict"; instructs the browser to use the javascript code in the
Strict mode.
Strict mode is useful to write "secure" JavaScript by notifying "bad syntax" into real errors. For example,
it eliminates accidentally creating a global variable by throwing an error and also throws an error for
assignment to a non-writable property, a getter-only property, a non-existing property, a non-existing
variable, or a non-existing object.
<!DOCTYPE html>
<html>
<body>
<h2>With "use strict":</h2>
<h3>Using a variable without declaring it, is not allowed.</h3>
<script>
"use strict";
x = 3.14; // This will cause an error (x is not defined).
</script>
</body>
</html>
Purpose of void 0
Void(0) is used to prevent the page from refreshing. It is commonly used for HTML documents that use
href="JavaScript:Void(0);" within an <a> element. i.e, when you click a link, the browser loads a new
page or refreshes the same page. But this behavior will be prevented using this expression. For example,
the below link notify the message without reloading the page
<a href="JavaScript:void(0);" onclick="alert('Well done!')">Click Me!</a>
preventDefault()
The preventDefault() method cancels the event if it is cancelable, meaning that the default action or
behaviour that belongs to the event will not occur. For example, prevent form submission when clicking
on submit button and prevent opening the page URL when clicking on hyperlink are some common use
cases.
Note: Remember that not all events are cancelable.
<a id="link" href="https://www.w3schools.com">Click me</button>
<script>
document.getElementById("link").addEventListener("click", function(event){
event.preventDefault();
});
</script>
Prevent the default function of a tag, then click on a href will not open new page.
stopPropagation()
<!DOCTYPE html>
<html>
<head>
<style>
div{
width: 200px;
height: 200px;
}
.parent{
width: 150px;
height: 150px;
background: #FF0000;
padding: 25px;
}
.child{
width: 150px;
height: 150px;
background: #00FF00;
}
</style>
<body>
<p>Click Red and Green color Div</p>
<div class="parent" onclick="parentFunc()">
<div class="child" onclick="childFunc(event)"></div>
</div>
<script>
function parentFunc(event) {
alert("Parent");
event.stopPropagation();
}
function childFunc() {
alert("Child");
}
</script>
</body>
</html>
Child div is inside parent div. So as default nature, if you click on child div, childFunc() and parentFunc()
both will be triggered. The stopPropagation() prevents propagation/spread of the same event from
being called.
Event capturing vs Event bubbling
Event capturing
When you use event capturing
the event handler of element1 fires first, the event handler of element2 fires last.
Event bubbling
When you use event bubbling
the event handler of element2 fires first, the event handler of element1 fires last.
BOM
The Browser Object Model (BOM) allows JavaScript to "talk to" the browser. It consists of the objects
navigator, history, screen, location and document which are children of the window. The Browser Object
Model is not standardized and can change based on different browsers.
window and document
Window Document
It is the root level element in any web It is the direct child of the window object. This is also
page known as Document Object Model(DOM)
By default window object is available You can access it via window.document or document.
implicitly in the page
It has methods like alert(), confirm() and It provides methods like getElementById,
properties like document, location getElementsByTagName, createElement etc
setTimeout vs setInterval
setTimeout(expression, timeout); runs the code/function once after
the timeout. setInterval(expression, timeout); runs the code/function repeatedly, with the length of
the timeout between each repeat. Example: setInterval fires again and again in intervals,
while setTimeout only fires once.
setTimeout(function(){ console.log("Good morning"); }, 2000);
setInterval(function(){ console.log("Good morning"); }, 2000);
Default parameters
Default function parameters allow named parameters to be initialized with default values if no value or
undefined is passed.
function add(x = 10, y = 20) {
return x+y;
}
console.log('Addition with passing value => ', add(3,6));
console.log('Addition with default value => ', add());
Addition with passing value => 9
Addition with default value => 30
Features of ES6
i. Support for constants or immutable variables
ii. Block-scope support for variables, constants and functions
iii. Arrow functions
iv. Default parameters
v. Rest and Spread Parameters
vi. Template Literals
vii. Multi-line Strings
viii. Destructuring Assignment
ix. Enhanced Object Literals
x. Promises
xi. Classes
xii. Modules