Skip to content

Javascript Language

Posted on:September 23, 2022 at 03:22 PM

Strict mode in JS

Effect of strict

JS internals

Two phases of JS

Hoisting

Execution context

Contents of execution context:

Errors in JS

Note: A variable can be redefined using var but not when using let or const.

JS event loop, call stack, callback queue

JS engine:

JS engine:

JS runtime (JRE)

Scope in JS

Note:

JavaScript basics

Type conversion vs Coercion.

5 primitive data types

  1. Numbers: Includes ALL numbers, integer and fraction.

    • % : remainder
    • 1/3= 0.33333 (no type coercion of result)
  2. Strings:

    • Use both " and '. You can use one inside another.
    • Use + to concatenate two strings or a string with a number, the result will be a number, this is called type coersion.
    • Use / to escape quotes in a string.
    • Use length property for string length.
  1. boolean: true, false

  2. null: Explicit null value assigned to variable.

  3. undefined : No value assigned to variable.

  4. Symbol(ES2015): Unique value that cannot be changed. Symbols are often used to add unique property keys to an object that won’t collide with keys any other code might add to the object, and which are hidden from any mechanisms other code will typically use to access the object.

  5. BigInt(ES2020): An int too large to fit in number type. Created by appending n to the end of an integer literal, or by calling the BigInt() constructor (but without the new operator)

  6. NaN: Numeric value that represents something that is…not a number for eg. 0/0, 1 + NaN.

Primitives vs. Objects (Primitive vs. Reference Types)

Variable

// Numbers:
1;
-99;
0.345345;

//Making variables with let:
let numberOfFriends = 1;

//Incrementing:
numberOfFriends += 3; //numberOfFriends is now 4

// Variables with const
const minimumAge = 21; //CANNOT REASSIGN!

//Booleans - true or false values
true;
false;
let isHappy = true;

//Naming Conventions
// Use upper camel-cased names:
let numberOfChickens = 6; //GOOD
// NOT THE JS WAY:
// let number_of_chickens = 6;

String built in methods

MATH object

Built-in methods

String/Template literals

Including JS files in html

Operators

const itemList = ["chair", "table", "box"];
// length is property of array itemList
length in itemList ? console.log("To be printed") : console.log("not printed");

Nullish coalescing(NC) operator vs logical OR

Optional chaining operator

Comparison operators

var x = 5;
x == "5"; //is true
x === 5; //is false

//"==" Does 'type coercion', ie make both sides of same type, then compare.

null == undefined; // true
null === undefined; // false

true == "1"; // true
true == "2"; // false
0 == false; // true
NaN == NaN; // false

Note: NaN is not comparable.

Logical operators

Truthy and falsey values

Falsey values

Conditionals

// the if statement can be used without else if and else
if() { }
else if() {//Notice the space between else and if }
else { }

// Loops
while() { }

for(init; condition; step) { }

// for of loop ( not supported in IE)
arr1 = [1,2,3,4,5];
for (let val of arr1) {
console.log(val);
}

// switch case, not common in JS
switch(expression) {
  case x:
    // code block
    break;
  case y:
    // code block
    break;
  default:
    // code block
}

Functions

Function expressions

// function statement
function funcName(arg1) {
  console.log("Hi " + arg1);
} // Notice no var in arg1, function declaration

// function expression
var funcName = function (arg1) {}; // Function expression

// funcName can be reassigned to a different value,
// in that case function will not be accessible.

Variable scope

Higher order functions

function vs method

this keyword in JS

this keyword and 4 ways to call a function.

Exception handling in JS

setInterval(), clearInterval()

Invoking an anonymous function:

// IIFE
(function() {
console.log("Hello World");
})()

// interval is in ms. Run func1 after every interval ms.
const setReturn = setInterval (function() {
  }, interval); // using anonymous function.

clearInterval(setReturn).

Set

Maps

Iterables in JS

JS Arrays

Array methods in JS

// Empty aray
let arr1 = [];
let arr2 = new Array();

typeof arr1;
// "object"

let nums = [1, 2, 3, 4];
// numscopy points to same array object and is equal ==
// modifying one will alter the other
let numscopy = nums;

// Array iteration
// we can also use normal for loop
arr1.forEach(function (item, index, arr) {
  console.log(item);
}); // Note that index and array can also be passed.

Array methods

// start: The index at which to start changing the array.
// deleteCount (Optional): An integer indicating the number of elements in the array to remove from start.
// item1, item2, ... Optional: The elements to add to the array, beginning from start.
// returns an array containing the deleted elements.

splice(start);
splice(start, deleteCount);
splice(start, deleteCount, item1);
splice(start, deleteCount, item1, item2, itemN);

Arrow functions

// function expression
const add = function (x, y) {
  return x + y
}

// Arrow function syntax
const add = (x, y) => {
  return x + y
}

// Arrow function with one argument
// no parentheses
const square = (x) => {
  return x ** 2
}

// implicit return
const square = (x) => x ** 2

// implicit return with brackets
const square = (x) => {
  x ** 2
}

// To return an object literal expression
// requires parentheses around expression
params => ({foo: "a"}) // returning the object

// Rest params are supported
(a, b, ...r) => expression

// Default parameters are supported
(a=400, b=20, c) => expression

// Destructuring within params supported
([a, b] = [10, 20]) => a + b;  // result is 30
({ a, b } = { a: 10, b: 20 }) => a + b; // result is 30

// cannot contain a line break between its parameters and its arrow
var func = (a, b, c)
  => 1;
// SyntaxError: Unexpected token '=>'

Constructor function:

Regular function:

Objects in JS

Initialising empty object in JS

Accessing objects with brackets and dot notation

Newer JS features

arguments object

Default params in functions

Spread operator in function calls

// Use of spread operator in function calls
function sum(x, y, z) {
  return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));

Spread operator in array and object literals

let numberStore = [0, 1, 2];
let newNumber = 12;
numberStore = [...numberStore, newNumber];

// pass all key:value pairs from an object
let objClone = { ...obj };

Rest params

Destructuring arrays and objects

// Assigning to new variable names
const o = { p: 42, q: true };
const { p: foo, q: bar } = o;

// Default values
const { a = 10, b = 5 } = { a: 3 };

console.log(a); // 3
console.log(b); // 5

Destructuring params

let a,
  b,
  rest;

  // a=10, b=20
[a, b] = [10, 20];

console.log(a);
// expected output: 10

console.log(b);
// expected output: 20
[a, b, ...rest] = [10, 20, 30, 40, 50];

console.log(rest);
// expected output: Array [30,40,50]

Storage in Browser

DOM

DOM manipulation workflow

DOM traversal.

Lifecycle DOM events

NodeList, HTMLCollection, arrays of objects

DOM object

Old DOM methods

New DOM methods

DOM manipulation

Separation of concern: Style is defined in CSS file and toggled in JS. You should avoid direct style changes in JS.

Change style of element

We can add style manually for eg tag.style.border etc, but we generally use classes.

// Define a class in CSS file. eg
   .my- class {
   color: blue;
   border: 10px solid red;
   }

// Select an element/tag in js file.
   tag=document.querySelector("h1")

//tag.classList.add("my-class").

classList.remove()
classList.toggle() // used for mouse clicks

Classlist

Node vs element in DOM

Traversing parent, child and sibling in DOM

Adding and removing element in DOM

Removing an element in DOM

DOM events

Debouncing and throttling

Adding event listeners the non optimal way

Correct way to add event listener (addEventListener)

Event Object

Form events and preventDefault

Input and change events

DOM Event propogation:

Event capturing/trickling

Event bubbling

Event delegation

DOM object hierarchy

Async Javascript

call stack

Web API and single thread

Callback hell

then and finally method in promise

Running promises in parallel

Promises

Manually creating your own promise.

// Creating a promise
const fakeRequest = url => {
  return new Promise((resolve, reject) => {
    const rand = MATH.random();
    setTimeout(() => {
      if (rand < 0.7) {
        resolve("your fake data here");
      }
      reject("request error");
    }, 1000);
  });
};

// Using the promise
fakeRequest("/dogs/1")
  .then(data => {
    console.log("done with request");
  })
  .catch(err => {
    console.log("there is error", err);
  });

Async functions

// declaring an async arrow function
const login = async () => {
  console.log("Hi There");
};

// declaring a normal async function expression
const login = async function () {
  console.log("Hi There");
};

// declaring a normal async function
async function login() {
  console.log("Hi There");
}

AJAX

API and JSON

HTTP status code

Quyery string and HTTP headers

XHR (old way of sending request in JS code)

fetch API

axios (latest)

Change content of element

tag.textContent : get/set text content inside an element, it ignores tags and recurse to get all text. You can’t set html tags with this, they will appear as strings on webpage.

text.innerHTML: get/set text + html tags. You can set html tags with this.

Change attribute of element

DOM events

To add event listener to nodeList(HTMLCollection)

for (i = 0; i < tagList.length; ++i) {
  tagList[i].addEventListener(click, function () {
    this.style;
  });
}

Difference between input and change event

Types of events

Keypress Vs keydown:

this keyword

this.person = "Ellie"; // person is now a global variable.

call(), apply() and bind()

var pokemon = {
  firstname: "Pika",
  lastname: "Chu ",
  // this method is bound to the pokemonn object.
  getPokeName: function () {
    var fullname = this.firstname + " " + this.lastname;
    return fullname;
  },
};

var pokemonName = function () {
  console.log(this.getPokeName() + "I choose you!");
};

// Bind this to pokemon object
var logPokemon = pokemonName.bind(pokemon);

logPokemon(); // 'Pika Chu I choose you!'

What is currying

Currying is a technique of evaluating function with multiple arguments, into sequence of functions with single argument.In other words, when a function, instead of taking all arguments at one time, takes the first one and return a new function that takes the second one and returns a new function which takes the third one, and so forth, until all arguments have been fulfilled.

// function currying using bind
function multiply(x, y) {
  console.log(x * y);
}

multiplyByTwo = multiply.bind(this, 2);
multiplyByThree = multiply.bind(this, 3);

multiplyByTwo(10);

// function currying using closures
function multiply(x) {
  return function (y) {
    console.log(x * y);
  };
}

multiplyByTwo = multiply(2);
multiplyByThree = multiply(3);

multiplyByTwo(4);

Polyfill for bind() method

// object to be bound
let name = {
  firstname: "Saurabh",
  lastname: "Prakash",
};

// Function to be bound
let printName = function (hometown, state) {
  console.log(`${this.firstname} ${this.lastname} ${hometown} ${state}`);
};

// Demo of bind
let printMyName = printName.bind(name, "Dehradun");
printMyName("Uttarakhand");

// Own implementation of bind
Function.prototype.mybind = function (...args1) {
  if (typeof this !== "function") {
    throw new Error(this + "can't be bound as it's not callable");
  }

  let obj = this,
    params = args1.slice(1);

  return function (...args2) {
    obj.apply(args1[0], [params, ...args2]);
  };
};

// test of custom implementation of bind
let printMyName2 = printName.bind(name, "Dehradun");
printMyName("Uttarakhand");

Asynchronous function

async and defer properties in script tag in HTML

OOP in JS

Three ways to create classes in JS

Note: object1.hasOwnProperty(‘age’), checks if object1 has own(not from proto chain) property ‘age’.

getter and setter

Static methods in JS

Inheritance between classes in JS

Encapsulation in JS

new keyword does four things

Prototype and prototype chain

OOP using contructor functions

// OOP using contructor functions
function Color(r, g, b) {
  this.r = r;
  this.g = g;
  this.b = b;
}

Color.prototype.rgb = function() {
  cons {r, g, b} = this;
  return `rgb(${r}, ${g}, ${b})`;
};

Color.prototype.hex = function() {
  cons {r, g, b} = this;
  return '#' + ((255 << 24) | ((byte)R << 16) | ((byte)G << 8) | ((Byte)B<<0)).toString(16).slice();
};

const color1 = new Color(23, 58, 126);
color1.hex();

const c1 = new Color(234, 128, 55, mycolor);
const c2 = new Color(134, 108, 115, mycolor);

// below is true as they point to
// same method
c1.rgb === c2.rgb;

OOP using class

// OOP using classes
// better than using constructor functions
class Color {

  constructor(r,g,b, name) {
    this.r = r;
    this.g = g;
    this.b = b;
    this.name = name;
  }

// will be automatically added to the prototype
rgb() {
  cons {r, g, b} = this;
  return `rgb(${r}, ${g}, ${b})`;
}

// will be automatically added to the prototype
hex() {
  cons {r, g, b} = this;
  return '#' + ((255 << 24) | ((byte)R << 16) | ((byte)G << 8) | ((Byte)B<<0)).toString(16).slice();
}

}

const c1 = new Color(234, 128, 55, mycolor);
const c2 = new Color(134, 108, 115, mycolor);

// below is true as they point to
// same method
c1.rgb === c2.rgb;

extends and super keyword

class cat extends Pet {
  // no need of constructor
  // as it is defined in the parent class

  // we can writye our own constructor
  constructor(name, age, livesLeft = 9) {
    super(name, age);
    this.livesLeft = livesLeft;
  }
}

To add a custom method to Array prototype

Array.prototype.myForEach = function (func) {
  for (i = 0; i < this.length; i++) {
    func(this[i]);
  }
};

Prototype chain

Note: In js every object has a method named hasOwnProperty(), this method is defined in “Object”, which is root object? Is Object.prototype the root object?

Closures

Conditions for a closure

Real world use of closures

ES6/ECMA2015

let Vs var

const func1 = function () {
  //using Const ensures catching unintentional reassignment of func1
};
console.log(x); // gives undefined
var x = 100;
console.log(x); // prints value of x

console.log(x); // throws ReferenceError exception, execution stops
let x = 100;
console.log(x); // prints value of x

let x;
console.log(x); // gives undefined
x = 100;
console.log(x); // prints value of x

Hoisting used by var keyword

Arrow function syntax

Built-in functions

Array functions

fill() and map()

let arr = new Array(100);

arr = arr.fill(0).map(() => Math.random());

arr = arr.fill(0).map(Math.random);

let arr = Array(100).fill(0).map(Math.random);

let arr = Array(100).fill().map(Math.random);

Note: map needs some values(even undefined) to work.

reduce

filter ()

promise

create you promises

async, await (es8)

promise.all()

let promises = [promise1, promise2, promise3];

promise
  .all()
  .then(() => {})
  .catch(err => console.error(err));

filter()

Note : JS builtin str1.split(” ”)// returns an array

sort()

promise()

promise.all()

Try catch in promises

Inheritance

ES6 Classes

class xyz extends baseClass {
  //note there is no function keyword in front of constructor
  constructor() {}
}

Polymorphism

JS built-in methods

Object.fromEntries()

const entries = new Map([
  ["foo", "bar"],
  ["baz", 42],
]);

const obj = Object.fromEntries(entries);

console.log(obj);
// expected output: Object { foo: "bar", baz: 42 }

JS for React

Ternary operator

Logical operators && or ||

// Ternary operator
const buttonLabel = playback === "stop" ? "play ▶️" : "stop ⏹️";
// Logical operator
const userComponent = isLoggedIn && getUserComponent();

Optional chaining && nullish coalascing operator

Closures

Lexical scoping

Template literals:

Tagged templates

Syntax: ${JS-expression} Usage: Used inside curly braces of JSX.

Nesting of templates

Within a backtick-delimited template, it is simple to allow inner backticks by using them inside an ${expression} placeholder within the template.

Tagged templates and escape sequences

Raw strings

Shorthand property names

{a, b, c} is same as {a: a, b: b , c: c}

Object initializer pattern

Object literal notation vs JSON

Shorthand method names

let o = {
  property: function (parameters) {},
  get property() {},
  set property(value) {},
};

// Same as
// Shorthand method names (ES2015)
let o = {
  property(parameters) {},
};

Computed property names

let i = 0;
let a = {
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
};

Arrow functions

Object Destructuring

const creatures = {
  human: ["👨🏿‍💼", "👩🏼‍💼", "🧑🏻‍💼", "👩🏾‍💻", "🧑‍💻"],
  supernatural: ["👾", "🤖", "👽", "👹", "👺"],
};
let human, supernatural;
({ human, supernatural } = creatures);
function MyReactComponent({ name, age }) {
  // ...
}
const { human: people = ["👨🏿‍💼"], supernatural = ["👾", "👽"] } = {
  human: ["👨🏿‍💼", "👩🏼‍💼", "🧑🏻‍💼"],
};
console.log(people); // ["👨🏿‍💼", "👩🏼‍💼", "🧑🏻‍💼"]
console.log(supernatural); // ["👾", "👽"]

// Nesting is also possible while destructuring
const creatures = {
  animals: {
    wildlife: ["🦂", "🐍"],
    pet: ["🐕", "🐈"],
  },
  human: ["👨🏿‍💼", "👩🏼‍💼", "🧑🏻‍💼"],
};
const {
  animals: { pet },
} = creatures;
console.log(pet); //  ["🐕", "🐈"]

Array destructuring

With the help of the destructuring assignment, an array can be unpacked in such a way that its values are extracted into distinct variables.

const array = [1, 2];
const [varForVal1, varForVal2] = array;
console.log(varForVal1); // 1
console.log(varForVal2); // 2

// variables are assigned from the left to the right of
// the array, so order is maintained.
const [fruit, veggie] = ["🍓", "🥦", "🍕", "🌮", "🥪", "🍔"];
console.log(fruit); // 🍓
console.log(veggie); // 🥦

// You can also skip values under consideration of the order.
const [fruit, , pizza, , , burger] = ["🍓", "🥦", "🍕", "🌮", "🥪", "🍔"];
console.log(fruit); // 🍓
console.log(pizza); // 🍕
console.log(burger); // 🍔

// You can also assign multiple values at
// once with the rest pattern.
const [fruit, veggie, ...junkfood] = ["🍓", "🥦", "🍕", "🌮", "🥪", "🍔"];
console.log(fruit); // 🍓
console.log(veggie); // 🥦
console.log(junkfood); // ["🍕", "🌮", "🥪", "🍔"]

// Array destructuring allows for default values.
const getFood = () => ["🍓", "🥦"];
const [fruit, veggie, junkfood = "🍕"] = getFood();
console.log(fruit); // 🍓
console.log(veggie); // 🥦
console.log(junkfood); // 🍕

Array destructuring in React

Array destructuring vs object destructuring

Parameter defaults

Spread operator

// Use case#1: Pass each element of an array
// as individual function argument.
const numbers = [11, 5, 3, 1, 26];
// Math.max expects to be called like Math.max(11,5,3,1,26)
console.log(Math.max(...numbers)); // 26

// Use case#2: Copy object properties to create a new object
const food = {
  breakfast: ["🥞", "🧇"],
  lunch: ["🍔", "🍟", "🍕"]
};
const foodAndDrinks = {
  ...food,
  drinks: ["🍷", "🍹", "🍺", "🥃"],
};

// Create a copy of an array.
const food = ["🥞", "🧇", "🍔", "🍟", "🍕"];
const copy = [...food];

Spread operator in React

const restaurantState = {
  drinks: ["🍷", "🍹", "🍺", "🥃"],
  food: ["🥞", "🧇", "🍔", "🍟", "🍕"],
  lastOrder: null
}
// the customer ordered a 🍔
const stateAfterOrder = {
  drinks: [...restaurantState.drinks], // copy drinks
  food: [...restaurantState.food], // copy food
  lastOrder:  "🍔" // override lastOrder
}

Rest operator

ESModules

Ternaries

Array Methods

Nullish coalescing operator

Optional chaining

Promises and async/await

Array methods