Giter Club home page Giter Club logo

explainjs's Introduction

ExplainJS

ExplainJS


"Explain JS" is a handbook that provides an in-depth explanation of the JavaScript programming language. It covers the fundamental concepts of JavaScript, including data types, functions, objects, and events. The handbook also dives into more advanced topics such as asynchronous programming with Promises and async/await, error handling, and best practices for writing clean and maintainable code. Additionally, the handbook includes code examples and practical exercises to help readers solidify their understanding of JavaScript concepts. Whether you're a beginner or an experienced developer, "Explain JS" is a comprehensive guide to mastering JavaScript.

Table of Contents

1. Introduction (5)

  1.1 what is javascript
  1.2 Use Of javascript
  1.3 History of javascript
  1.4 javascript data types
  1.5 type grammer

2. Variable

  2.1 what are variables

  2.2 types of variables

3. Scope(4)

  3.1 What is scope
  3.2 What is lexical scope model
  3.3 What is scope chaining
  3.4 What is shadowing

4. Closure(5)

   4.1 What is closure

5. Functions    [History of javascript] (#-some jkdsf)
6. Hoisting    [History of javascript] (#-some jkdsf)
7. Objects    [History of javascript] (#-some jkdsf)
8. Arrays    [History of javascript] (#-some jkdsf)
9. String    [History of javascript] (#-some jkdsf)
10. Classes    [History of javascript] (#-some jkdsf)
11. Error Handling    [History of javascript] (#-some jkdsf)
12. Async javascript

  12.1 What is Asynchrony in javascript
  12.1 What do you mean by synchronous code in javascript
  12.1 What do you mean by asynchronous code in javascript
  12.1 What is the diffrence between synchrnous js and async js
  12.1 What is the benefit of async js compare and explain

13. Callbacks(2)

  13.1 What is callback function
  13.2 What is the drawback of callback function

14. Promises(3)

  14.1 What is promise
  14.2 What is the drawback of promise
  14.3 promise methods

15. Async & Await

  15.1 what is async await combination

  15.1 what is the benefit to use async await



1. Introduction

1.1 What is javascript?

JavaScript is a popular programming language used for creating dynamic web pages and applications. It is a client-side scripting language, which means it is executed by the user's browser rather than on the server-side. This allows developers to create dynamic and interactive web applications that can respond to user actions in real-time.

JavaScript was created in 1995 by Brendan Eich while he was working at Netscape Communications Corporation. Originally, it was called Mocha and then later changed to LiveScript before finally being named JavaScript. Since then, it has become one of the most widely used programming languages in the world, used by millions of developers and powering countless websites and applications.

One of the key features of JavaScript is its ability to manipulate HTML and CSS elements, allowing developers to create dynamic and interactive web pages. JavaScript can be used to validate user input, create animations and effects, and handle events such as clicks and keystrokes.

JavaScript is a versatile language that can be used for both front-end and back-end development. On the front-end, JavaScript can be used with HTML and CSS to create web pages and applications. On the back-end, it can be used with frameworks such as Node.js to create server-side applications.

Another advantage of JavaScript is its large and active community of developers. This community has created a vast ecosystem of libraries, frameworks, and tools that make it easier for developers to build complex web applications.

In conclusion, JavaScript is a powerful and versatile programming language that is essential for web development. Whether you're a beginner or an experienced developer, learning JavaScript is a valuable skill that can open up many opportunities in the world of web development.

Read More:what is javascript

tick javascript data types

In JavaScript, a data type refers to the type or category of a value that can be stored in a variable or passed as an argument to a function. Every value in JavaScript has a data type, which determines the type of operations that can be performed on that value and how that value is stored and processed by the JavaScript engine.

JavaScript has two main categories of data types: primitive data types and non-primitive data types. Primitive data types are the most basic data types, and they include number, string, boolean, null, undefined, and symbol. Non-primitive data types, also known as reference types, are more complex data types, and they include objects, arrays, functions, and others.

The data type of a value in JavaScript is automatically determined by the JavaScript engine based on the value itself. For example, if a value is a number, its data type is number. If a value is a string, its data type is string. Developers can also explicitly define the data type of a variable or value using type conversion functions or by explicitly assigning a value to a variable with a specific data type.

Understanding data types is an important aspect of programming in JavaScript, as it affects how values are stored and processed, and can impact the performance and behavior of a program.

Primitive Data Types:

Number: Represents numeric values, including integers and floating-point numbers. BigInt: Represents integers with arbitrary precision. Boolean: Represents a logical value of either true or false. String: Represents a sequence of characters. Symbol: Represents a unique identifier that is not equal to any other value.

Non-Primitive Data Types:

Object: Represents a collection of properties and methods. Array: Represents an ordered list of values. Map: Represents a collection of key-value pairs. Set: Represents a collection of unique values. Function: Represents a block of code that can be called and executed. Date: Represents a date and time value. RegExp: Represents a regular expression object used for pattern matching. Error: Represents an error object containing information about an error that occurred during execution. Promise: Represents a promise for a value that may not be available yet. Proxy: Represents a proxy object that can intercept and customize operations performed on another object. It's worth noting that although there are many data types in JavaScript, all of them are ultimately derived from the primitive data types. For example, objects, arrays, and functions are built upon the primitive data types, and their behavior is determined by the underlying primitive data types they are built upon.

type grammer

primitive behaviour

1.1 Primitive immmutibility:

all primitive value are immutable it means you cant change the contents of primitive -- reassingment possible ,new value also create but original value remain intact

The nature of primitive values being immutable is not affected in any way by how the variable or object property holding the value is declared. For example, whether const, let, or var are used to declare the greeting variable above, the string value it holds is immutable.

const doesn't create immutable values, it declares variables that cannot be reassigned (aka, immutable assignments) -- see the "Scope & Closures" title of this series for more information.

primitive with properties

properties can not added to primitives but property access is allowed except null and undefined

  • non nullish primitives have some built in methods says toString(),valueOf()
  • coerscion behavior k/a autoboxing can explain these

primitive assignments

any assignment of values from one to another is value copy each of these own copy of value

string behaviour

1.string character access

string can follow style to get access of characters means by index help we can access characteres if index not number it will try to coerce to number if index not in 0- length-1 or NaN or not a number value type the access will treated as property accss with string property equivalnrt name; if property access fail result is undefined

string comparison[equality and relational ordering]

comparison are sensitive to actual string contents underlying code codepoints non BPM unicode characters

  • equality abd relational operation are case sensitive;

String Equality

=== or == operators alogn with negation != or !==

string concatenation

2 or more values can be easily cconcatenated by + operator if one is string other will coerce to string even if empty thinks wd work other option for concatenation is concat and join method

string value methods

charAt() at() charCodeAt() codePointAt() substr()/substring()/slice() concat() indexOf inludes() search() trim() split() and others

2. Variables

tick 2.1 What are variables?

In JavaScript, variables are used to store data or values for later use in a program. There are three types of variables in JavaScript: var, let, and const.

var is the oldest type of variable in JavaScript and has been used since the beginning. It has a function scope or global scope, depending on where it is defined. A variable declared with var can be re-declared and updated anywhere in the scope, which can cause unexpected behavior in your program.

let was introduced in ES6 (ECMAScript 2015) and has block scope. A variable declared with let can only be accessed within the block it was declared in. It cannot be re-declared within the same block scope, but it can be updated with a new value.

const was also introduced in ES6 and has block scope, just like let. However, a variable declared with const cannot be reassigned once it is defined. This means that once you set a value to a const variable, you cannot change it later. You can, however, modify the value of the properties of an object or the elements of an array that is assigned to a const variable.

The reason why const is often used in ES6 is that it helps prevent bugs caused by accidentally reassigning a value to a variable. By using const, you can ensure that a variable's value remains the same throughout your program, which can make it easier to debug and maintain. const also helps improve the readability and clarity of your code, as it makes it clear which variables are meant to be constant and which can be updated.

Overall, let and const provide more granular control over variable scope and help prevent errors that can occur with var. const is especially useful when you need to define a value that should not be changed, as it enforces immutability.

tick 2.1 different kind of variable declaration?

let var and const

Let's compare and contrast the features of let, var, and const in JavaScript:

1. Scope:

var: var variables are function-scoped. They are accessible within the function they are declared in, as well as within nested functions. If declared outside of any function, they become global variables.

let and const: Both let and const variables are block-scoped. They are limited to the block (enclosed within curly braces) they are defined in, such as within an if statement, for loop, or function block.

2. Hoisting:

var: var variables are hoisted to the top of their scope during the compilation phase. This means you can access var variables before they are declared, but they will have the value undefined until assigned.

let and const: Unlike var, let and const variables are not hoisted. They are not accessible before their declaration, resulting in a ReferenceError if accessed prematurely.

3. Reassignment:

var and let: Both var and let variables can be reassigned with new values within their scope.

const: const variables are read-only and cannot be reassigned once they are assigned a value. However, for objects and arrays, the properties or elements within the object or array can still be modified.

4. Temporal Dead Zone (TDZ):

let and const: let and const variables have a TDZ, which is a period before their declaration in which they cannot be accessed. Accessing them during the TDZ results in a ReferenceError.

5. Use Cases:

var: var variables are commonly used when you need variables with function scope or when you intentionally want variables to be hoisted.

let: let variables are recommended when you need block scope and the ability to reassign values.

const: const variables are useful when you want to declare variables with a constant value that should not be reassigned.

6. Redeclaration:

var: var allows for redeclaration of a variable within the same scope. This can lead to potential bugs and variable shadowing issues.

let and const: Both let and const do not allow redeclaration of a variable within the same scope. Attempting to redeclare a let or const variable will result in a SyntaxError.

7. Function-level scoping:

var: var variables are function-scoped, meaning they are accessible throughout the entire function they are declared in, regardless of block scopes within that function.

let and const: Both let and const variables are block-scoped, meaning they are limited to the block they are defined in. They are not accessible outside of the block, including within nested blocks.

8. Initialization:

var and let: var and let variables can be declared without being immediately initialized. They will have the value undefined until they are assigned a value.

const: const variables must be initialized with a value at the time of declaration. They cannot be declared without an initial value.

9.Performance considerations:

let and const: let and const variables offer better performance optimizations compared to var in certain scenarios, such as in loops. This is because let and const variables have block scope, allowing them to be optimized more effectively by the JavaScript engine.

10. Global object property:

var: var variables declared in the global scope become properties of the global object (window object in browsers or global object in Node.js).

let and const: let and const variables declared in the global scope do not become properties of the global object. They remain confined to the global scope.

Function reordering: let and const: When using let or const within a block scope, they are not affected by function reordering. This means that if a function is defined after the block, the variables declared with let or const are still scoped to the block and not the function. var: Variables declared with var are function-scoped and can be affected by function reordering. If a function is defined after the block where var variables are declared, the variables will be scoped to the function instead of the block.

Global namespace pollution: var: Variables declared with var in the global scope can potentially lead to global namespace pollution. This is because var variables are attached to the global object (e.g., window in browsers), making them accessible and potentially conflicting with other global variables or libraries. let and const: Variables declared with let or const in the global scope do not pollute the global namespace. They are confined to the global scope but are not attached to the global object.

Use in loops: var: var variables have function scope, meaning that if they are used in a loop, their value persists outside the loop after the loop execution. let and const: let and const variables have block scope, which is particularly useful in loops. They are scoped to the block, so each iteration of the loop has its own independent instance of the variable. // Example using a for loop for (var i = 0; i < 5; i++) { // var keeps its value after the loop } console.log(i); // Output: 5

for (let j = 0; j < 5; j++) { // let has block scope, separate for each iteration } console.log(j); // ReferenceError: j is not defined These additional features and differences highlight some of the nuances and behavior of let, var, and const in JavaScript. It's essential to consider these differences when choosing the appropriate variable declaration keyword based on your specific needs and coding best practices.

Temporal Dead Zone (TDZ) behavior: let and const: Variables declared with let and const are subject to the Temporal Dead Zone (TDZ). During the TDZ, accessing the variable before its declaration results in a ReferenceError. The TDZ ends once the variable is declared. var: Variables declared with var are not affected by the TDZ. They can be accessed and will have the value undefined until they are assigned a value.

Block-level redeclaration: let and const: Redeclaring a variable with let or const within the same block scope results in a SyntaxError. var: Redeclaring a variable with var within the same block scope is allowed, and it simply creates a new variable with the same name, potentially leading to variable shadowing and bugs.

Use in closures: let and const: Variables declared with let or const in a closure retain their value from the time the closure is created. var: Variables declared with var in a closure are bound to the variable's value at the time the closure is executed.

Strict mode behavior: let and const: When using strict mode ("use strict";), redeclaring a variable with let or const within the same scope is not allowed and results in a SyntaxError. var: In strict mode, redeclaring a variable with var within the same scope is also not allowed and results in a SyntaxError.

Function expressions and declarations: var: Variables declared with var are function-scoped and are accessible within the entire function, regardless of whether they are declared before or after they are used. let and const: Variables declared with let or const have block scope and are subject to the temporal dead zone. They must be declared before they are used within the block scope.

Use in the global scope: var: Variables declared with var in the global scope become properties of the global object (window object in browsers or global object in Node.js). let and const: Variables declared with let or const in the global scope do not become properties of the global object. They remain confined to the global scope.

Variable initialization: var and let: Variables declared with var or let are initialized with the value undefined if not explicitly assigned a value. const: Variables declared with const must be initialized with a value at the time of declaration. It is not possible to declare a const variable without assigning a value.

Use in for...in and for...of loops: var: When used in for...in or for...of loops, variables declared with var are scoped to the function containing the loop, rather than being scoped to the loop itself. let and const: When used in for...in or for...of loops, variables declared with let or const are scoped to the loop iteration and do not leak outside of the loop.

Use in setTimeout and setInterval: var: When used with setTimeout or setInterval, variables declared with var retain their value from the time the timer is set until it fires. let and const: When used with setTimeout or setInterval, variables declared with let or const retain their value from the time the timer fires.

Use in closures: let and const: Variables declared with let or const in a closure maintain their individual copies for each closure instance. Each closure captures a unique snapshot of the variables at the time of creation. var: Variables declared with var in a closure are shared among all instances of the closure. Any modification made to the variable in one closure affects all closures referencing that variable.

Access before declaration: var: Variables declared with var are subject to hoisting, which means they can be accessed before they are declared in the code. However, they will have the value undefined until they are assigned a value. let and const: Variables declared with let or const are not hoisted and cannot be accessed before they are declared. Accessing them before the declaration will result in a ReferenceError.

Block scoping and variable shadowing: let and const: Variables declared with let and const have block scope, meaning they are limited to the block in which they are declared. They can be redeclared within nested blocks, effectively shadowing variables with the same name in the outer scope. var: Variables declared with var have function scope and can be accessed throughout the entire function, potentially leading to unintended variable shadowing and scope-related issues.

Use in object mutation: let, var, and const: All three keywords allow you to modify the properties of an object declared with them. However, const prevents the reassignment of the entire object to a new value.

Use in loops and closures: let: Using let in loops creates a new block scope for each iteration, allowing variables to retain their values without leaking to the outer scope. It is commonly used to solve the "closure in a loop" problem. var: Using var in loops does not create a new block scope for each iteration, which can lead to issues with closures and unintended variable sharing.

Use in closures and asynchronous operations: let and const: Variables declared with let or const in closures or asynchronous operations retain their individual copies for each closure or callback invocation. This ensures that each instance of the closure or callback captures the correct value at the time of creation. var: Variables declared with var in closures or asynchronous operations are shared among all instances of the closure or callback. This can lead to unexpected behavior if the variable is modified asynchronously.

Use in redeclaration within nested blocks: let and const: Redeclaring a variable with the same name within nested blocks using let or const creates a new variable specific to the inner block, effectively shadowing the outer variable. var: Redeclaring a variable with the same name within nested blocks using var does not create a new variable. The inner declaration modifies the value of the outer variable.

3. Scope

tick 3.1 What is scope?

In JavaScript, "scope" refers to the accessibility of variables, functions, and objects within a particular part of a program. Each variable and function has a scope, which determines where it can be accessed within a program.

📚 Explore: scope

tick 3.2 What is lexical scope model?

In JavaScript, the lexical scope model is used to determine the scope of variables and functions. It means that the scope of a variable or function is determined by where it is defined in the code, and not where it is called from.

📚 Explore: lexicalscopemodel

tick 3.3 What is scope chaining?

Scope chaining refers to the process by which JavaScript searches for a variable or function within nested scopes. When JavaScript encounters a variable or function reference within a function, it first checks the local scope of that function. If the variable or function is not found in the local scope, JavaScript then searches in the next outer scope, and so on, until it either finds the variable or function or reaches the global scope.

📚Explore: scope-chaining

tick 3.4 What is shadowing?

DEFINITION : when a variable declared within a certain scope [like function scope or block scope] has a same name as variable declared in an outer scope.The inner variable "shadows" or "hides" the outer variable within the scope it is defined. example :

📚Explore: shadowing


⬆ Return to top

4. Closure or lexical closure or function closure

(links 1) https://www.freecodecamp.org/news/lets-learn-javascript-closures-66feb44f6a44/

motivation for function closure

for security stand point principal of least exposure it suggest a defensive appproach to software architecture in which system has to be designed to function with leat privilege least exposure and least access if each component is connected with minimum necasary capbaility overall system is stronger from security stand point bcz comporimise or failure in one part has minimized impact on the system polp - focus on system level component design pole- focuses on lower level well apply it to how scope interact with each other

In following POLE, what do we want to minimize the exposure of? Simply: the variables registered in each scope.

Think of it this way: why shouldn't you just place all the variables of your program out in the global scope? That probably immediately feels like a bad idea, but it's worth considering why that is. When variables used by one part of the program are exposed to another part of the program, via scope, there are three main hazards that often arise:

  1. NAMING COLLISIONS:
  2. UNEXPECTED BEHAVIOR:
  3. UNINTENDED DEPENDENCY:

POLE, as applied to variable/function scoping, essentially says, default to exposing the bare minimum necessary, keeping everything else as private as possible. Declare variables in as small and deeply nested of scopes as possible, rather than placing everything in the global (or even outer function) scope.

If you design your software accordingly, you have a much greater chance of avoiding (or at least minimizing) these three hazards.

CHECK THIS OUT FOR MORE CLARITY OF ABOVE THOUGHTS

function diff(x,y) {
    if (x > y) {
        let tmp = x;
        x = y;
        y = tmp;
    }

    return y - x;
}

diff(3,7);      // 4
diff(7,5);      // 2

In this diff(..) function, we want to ensure that y is greater than or equal to x, so that when we subtract (y - x), the result is 0 or larger. If x is initially larger (the result would be negative!), we swap x and y using a tmp variable, to keep the result positive.

In this simple example, it doesn't seem to matter whether tmp is inside the if block or whether it belongs at the function level—it certainly shouldn't be a global variable! However, following the POLE principle, tmp should be as hidden in scope as possible. So we block scope tmp (using let) to the if block.****

what is closure?[function closure]

closure is javascript feature that allows a function to access variables from an outer (enclosing) function even after function has finished executing . OR in other words a closure allow a function to "remember" the values of variables in it lexical environment when it was created. OR a closure allows a function to remember and access variables from its parent function, even if that parent function has already completed its execution. OR a closure is created when an inner function "closes over" (captures) variables from its outer function, allowing the inner function to retain access to those variables even after the outer function has finished executing and u can update or whatever those variables.

OR

closure is observed when a function uses variables from outer scope even while running in a scope where those variable woudnot be accesible;

3 important point to notice

  • must be a function involved
  • must reference at leat one variable from an outer scope
  • must invoke in different branch of the scope chain from the variables;

why do we need closure?

they provide a way to create and maintain private data and functions In summary, closures are crucial for data encapsulation, managing state, working with asynchronous operations, creating reusable function factories, and maintaining context for event handlers and callbacks. They enable more flexible and organized JavaScript code compared to not using closures.

benefit of closure

  1. data encapsulation
  2. stateful functions
  3. callback and async operations
  4. function factories
  5. currying
  6. memory efficiency
  7. modular programming

📚Explore: benefit of closure

disadvantages of closure

  1. memory consumption
  2. performance overhead
  3. complexity and maintenance
  4. security concerns
  5. memory rentention
  6. context traps
  7. hard to garbage collect
  8. maintenance and scope management

📚Explore: disadvantages of closure

common misconception around closure

  1. inner function closes over value of variable in outer scope not the variable itself
var keeps=[];
for(var i=0;i<3;i++){

  keeps[i]=function keepI(){
    //closure over i
    return i;
  }
}
keeps[0]();   // 3 -- WHY!?
keeps[1]();   // 3
keeps[2]();   // 3
// answer 0 1 2 will be misconcetion because var i value has been updated and final value be 3 which will be reassign to i because it is in the scope
  1. invoking a function that make use of lexical scope lookup
function say(myName) {
    var greeting = "Hello";
    output();

    function output() {
        console.log(
            `${ greeting }, ${ myName }!`
        );
    }
}

say("Kyle");
// Hello, Kyle!
  1. global scope variables essentially cannot be (observably) closed over, because they're always accessible from everywhere. No function can ever be invoked in any part of the scope chain that is not a descendant of the global scope.
var students = [
    { id: 14, name: "Kyle" },
    { id: 73, name: "Suzy" },
    { id: 112, name: "Frank" },
    { id: 6, name: "Sarah" }
];

function getFirstStudent() {
    return function firstStudent(){
        return students[0].name;
    };
}

var student = getFirstStudent();

student();
// Kyle
  1. Variables that are merely present but never accessed don't result in closure
function lookupStudent(studentID) {
    return function nobody(){
        var msg = "Nobody's here yet.";
        console.log(msg);
    };
}

var student = lookupStudent(112);

student();
// Nobody's here yet.
  1. If there's no function invocation, closure can't be observed
function greetStudent(studentName) {
    return function greeting(){
        console.log(
            `Hello, ${ studentName }!`
        );
    };
}

greetStudent("Kyle");

// nothing else happens
  1. Though the enclosing scope of a closure is typically from a function, that's not actually required; there only needs to be an inner function present inside an outer scope
// ****************************** START FILE********************************************
var hits{
  // an outer scope (but not a function)
  let count=0;

  hits=function getCurrent(){
    count=count+1;
    return count;
  }
}
hits()
hits()
hits()

// ******************************END FILE





⬆ Return to top

Functions

function : A set of statements that performs a task or calculates a value and where there is some obvious relationship between the inputs and outputs.

Function Declaration

A function definition or function declaration or function statement consists of "function" keyword followed by:

  • the name of the function

  • A list of parameters to the function ,enclosed in parentheses and separated by commas

  • the javascript staements that define the function enclosed in curly braces.

  • primitive parameter passed by value any change in function not reflected in calling function or globally

 function squareModifiedNumber(num) {
            num = num + 1;
            return num * num;

        }
        let num = 6;
        console.log(num)
        console.log(squareModifiedNumber(num));
        console.log(num);
  • non primitive [array,user defined objects] if you pass as parameter any change in objects's property ,reflect change outside the function
 function getPersonDetail(personObject) {
            // modify son name here
            personObject.name = "nick";
        }

        var person = { name: "John", age: 30, };
        var name, modifiedName;
        name = person.name;  // name variable contain John
        getPersonDetail(person);
        modifiedName = person.name;  // modifiedName variable contain nick
                                    //name property of object person is modified

Function expression

The function keyword can be used to define a function inside an expression.

const getRectArea = function(width, height) {
  return width * height;
};

console.log(getRectArea(3, 4));
// expected output: 12
  • a function expression can be assigned to a variable
  • after a function expression has been stored in a variable the variable can be used as a function
  • function stored in variables do not need function names they are always invoked[called] using variable name

Function Invocation

  • function invocation is the process of calling a function by its name.
  • function invocation is done by using the function name followed by parentheses.
  • function invocation can be done using the function name or the function reference.

different types of function

  1. Pure functions Pure functions are functions that always return the same output for the same input and do not have any side effects, meaning they do not modify any external state or variables. Pure functions are easy to test and reason about because they do not depend on any external state.
       function add(a, b) {

return a + b; }







2. Higher order functions

Higher order functions are functions that take other functions as arguments and/or return functions as their result. These functions are often used for composition and abstraction.
```js

function applyOperation(x, y, operation) {
return operation(x, y);
}

function multiply(x, y) {
return x * y;
}

applyOperation(2, 3, multiply); // Output: 6

In this example, applyOperation() is a higher order function that takes two numbers x and y and a function operation as arguments, and returns the result of calling operation(x, y).

The multiply() function is a function that takes two numbers x and y and returns their product. We pass this function as an argument to applyOperation() to multiply the two numbers 2 and 3.

  1. recursive functions

Recursive functions are functions that call themselves until they reach a base case. Recursive functions are often used for tasks that involve a repeating pattern or structure.

function factorial(n) {
  if (n <= 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

factorial(5); // Output: 120

In this example, factorial() is a recursive function that calculates the factorial of a number n. The base case for the function is when n <= 1, in which case it returns 1. Otherwise, it multiplies n by the result of calling factorial(n - 1).

  1. Anonymous functions

Anonymous functions are functions that do not have a name and are defined inline. They are often used as callbacks or as arguments to other functions.

setTimeout(function() {
  console.log("Hello, world!");
}, 1000);

In this example, setTimeout() is a function that takes a function as its first argument and a time delay in milliseconds as its second argument. The anonymous function passed as the first argument will be executed after a delay of 1000 milliseconds and will log "Hello, world!" to the console. 5. Arrow functions Arrow functions are a shorthand way to define functions in JavaScript. They are often used for writing more concise and readable code.

const add = (a, b) => a + b;

Arrow functions have a few key differences from traditional functions:

They have a more concise syntax, with the arrow => replacing the function keyword. They do not have their own this value. Instead, they use the this value of the surrounding context. They cannot be used as constructors.

  1. generator functions

Generator functions are functions that can be paused and resumed, allowing them to generate a series of values over time. They are often used for implementing iterators and asynchronous programming.

function* countUpTo(n) {
  let i = 0;
  while (i < n) {
    yield i;
    i++;
  }
}

const counter = countUpTo(5);
console.log(counter.next().value); // Output: 0
console.log(counter.next().value); // Output: 1
console.log(counter.next().value); // Output: 2

In this example, countUpTo() is a generator function that takes a number n and generates a series of values from 0 up to n-1. The yield keyword is used to pause the function and return a value, and the function can be resumed by calling the next() method on the iterator object returned by the function.

Generator functions have a few key differences from traditional functions:

They use the function* syntax instead of the function syntax. They can pause and resume their execution using the yield keyword. They return an iterator object that can be used to iterate over the values they generate.

  1. async functions

    Async functions are a way to write asynchronous code in a more synchronous-looking style. They are often used for working with APIs or making network requests.

async function getData() {
  const response = await fetch('https://example.com/data');
  const data = await response.json();
  return data;
}

getData().then(data => console.log(data));

In this example, getData() is an async function that fetches data from a remote server and returns it as JSON. The await keyword is used to wait for the fetch() and json() methods to complete before returning the data.

Async functions have a few key differences from traditional functions:

They use the async keyword to indicate that they are asynchronous. They can use the await keyword to pause their execution until an asynchronous operation completes. They always return a promise, which can be used to handle errors and data returned from the function.

  1. callback functions -Callback functions are functions that are passed as arguments to other functions, and are executed when a certain event occurs or when the parent function completes. They are often used for event handling and asynchronous programming. javascript
function getData(callback) {
  const response = fetch('https://example.com/data');
  response.then(data => callback(data));
}

getData(data => console.log(data));

In this example, getData() is a function that fetches data from a remote server and passes it to a callback function when the data is available.

Callback functions have a few key differences from traditional functions:

  • They are typically passed as arguments to other functions.
  • They are executed asynchronously, often in response to an event or after an asynchronous operation completes.
  • They can be used to provide a way for code to respond to events and handle asynchronous operations.

First class functions

  • A programming language is said to have first class functions if functions in that language are trated like any other variable.
const  sayHi = function() {
  console.log("Hi");
}
sayHi();
  • first class function can be assigned to other variables
  • it can be passed as an argument to other functions
  function sayHello() {
           return 'hello';
        }

        function greet(helloMessage, name) {
            console.log(helloMessage() + " " + name);
        }
        greet(sayHello, "John");
  • it can be returned by other functions
function sayHello() {
   return function() {
      console.log("Hello!");
   }
}

we can invoke the function using the return value of the function in 2 ways:

  1. using double parenthesis
function sayHello() {
 return function() {
    console.log("Hello!");
 }}
sayHello()();
// Hello!
  1. using variable
const sayHello = function() {
   return function() {
      console.log("Hello!");
   }
}
const myFunc = sayHello();
myFunc();
// Hello!

Higher order function

A Higher-Order function is a function that receives a function as an argument or returns the function as output.

Arrow function

  • Arrow functions are a new way to write functions in JavaScript.
  • arrow functions are always anonymous.



⬆ Return to top

Hoisting in javascript

  • Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their scope before code execution.
  • Hoisting is a behavior that occurs when a variable or function is declared, but before it is declared, it is used.
hoist();
function hoist()
{
   console.log('hello everyone i am hoisted to top');
}

Variable hoisting

  • Variable hoisting is a JavaScript mechanism where variables declarations are moved to the top of their scope before code execution.
  • Variable hoisting is a behavior that occurs when a variable is declared, but before it is declared, it is used.
  • only var is hoisted and not let and const
  • because of hoisting, var are initialized with undefined.
// only var can be hoisted
console.log(a);
var a = 10;
//outout: undefined;
  • let and const are not hoisted because they are block scoped and not accessible outside of their block.
// let and const are not hoisted
console.log(b);
console.log(c);
let b=10;
const c=23;
//outout: Uncaught ReferenceError: Cannot access 'b' before initialization
  • var is hoisted because it is a function scoped variable.
  • temporary variables are not hoisted.
  • temporal dead zone is a part of the JavaScript language where variables are not accessible.
  • let and const are in the temporal dead zone.

Function hoisting




⬆ Return to top

Objects

  • Objects are containers that store data and functionality.
  • objects contain data as key value pairs.
  • in javascript, objects are special data types.
const cup={
   color:'red',
   size:'small',
   material:'plastic'
}
  • objects are mutable and can be changed.
  • mutable means that the object can be changed.

Object Methods

  • objects methods are functions that are stored in the object as properties.
  • object properties can be primitive values or other objects or functions.
  • object properties can be accessed using dot notation or bracket notation.

Creating objects

Following are the ways to create objects in JavaScript:

  • Create a single object, using an object literal.
const person={
   name:'sfz',
   age:18,
   address:'india'
}
  • Create a single object, with the keyword new.
const person=new Object();
person.name='sfz';
person.age=18;
person.address='india';
  • Define an object constructor, and then create objects of the constructed type.
function Person(name,age,address){
   this.name=name;
   this.age=age;
   this.address=address;
}
const person1=new Person('sfz',18,'india');
const person2=new Person('sdf',19,'india');
  • Create an object using Object.create().
const person=Object.create(Object.prototype);
person.name='sfz';
person.age=18;
person.address='india';

How to access object properties

  • properties are the values stored in an object.
  • properties can be accessed using dot notation or bracket notation.
const person={
   name:'sfz',
   age:18,
   address:'india'
}
// access using dot notation
console.log(person.name);      // objectName.propertyName
// access using bracket notation
console.log(person['name']);   // objectName[propertyName]
// access using expression
console.log(person[x]);        // x='name' person[x]
  • properties can usually be changed , added or removed.
  • but some properties are read-only.

Javascript Constructor Function

  • object literal only create one object at a time.
  • when we want to create multiple objects, we use constructor function.
  • A constructor function is a function that is used to create objects.

Constructor function syntax

  • A constructor function is defined using the function keyword.
  • First letter of the function name is capitalized.
  • A contructor function execute with the "new" keyword.
function Person(name,age,address){
   this.name=name;
   this.age=age;
   this.address=address;
}

let person1=new Person('sfz',18,'india');
console.log(person1.name);
  • when a function is executed with the "new" keyword,it does folllowing things:
    • creates a new empty object and assign it to the this variable.
    • the function body executes.Usually it modified "this" ,adds new properties to the object.
    • the value of the this variable is returned.
function Person(name,age,address){
   // this={}
   this.name=name;
   this.age=age;
   this.address=address;
   // retunr this;
}

Return from a constructor function

  • usually, the return value of a constructor function is the object that is created.
  • constructor main task is to write stuff in "this" and it automatically become the result.
  • But if there is a return statement the rule is simple
    • if return statement is called with an object ,then the object is returned instead of this.
    • if return is called with a primitive , its ignored and this is returned.
function BigUser() {

  this.name = "John";

  return { name: "Godzilla" };  // <-- returns this object
}

alert( new BigUser().name );  // Godzilla, got that object
function SmallUser() {

  this.name = "John";

  return; // <-- returns this
}

alert( new SmallUser().name );  // John

NOTE : usually contructor dont have any return statement explicitly.

Object properties configuration

data properties

  • object properties ,besides a value have three configuration properties:
    • writable: boolean, whether the property can be changed or not.
    • enumerable: boolean, whether the property is included in for...in loops or not.
    • configurable: boolean, whether the property can be deleted or not. NOTE : The method Object.getOwnPropertyDescriptor allows to query the full information about a property.The syntax as follows:
let descriptor = Object.getOwnPropertyDescriptor(obj, prop);

obj:The object to get information from. propertyName:The name of the property. The returned value is a so-called “property descriptor” object: it contains the value and all the flags.

let user = {
   name: "John",
   age: 30
};
let descriptor = Object.getOwnPropertyDescriptor(user, "name");
console.log(descriptor); 

accessor properties

  • object properties ,besides a value have three configuration properties: - writable: boolean, whether the property can be changed or not. - enumerable: boolean, whether the property is included in for...in loops or not. - configurable: boolean, whether the property can be deleted or not.

  • accessor properties are used to get and set values of properties.

  • accessor properties are defined using the get and set keywords.

  • getter: function that returns the value of the property.

  • setter: function that sets the value of the property.

  • getter and setter can be used together.

Object Prototype and Inheritance

What is prototype?

In javscript ,objects have a special hidden property [[Prototype]],that is either null or references another object ,that object is called the prototype.

  • When we read a property from object, and it’s missing, JavaScript automatically takes it from the prototype. In programming, this is called “prototypal inheritance”.
  • The property [[Prototype]] is internal and hidden, but there are many ways to set it.One of them is to use the special name proto, like this:
let animal = {
  eats: true
};
let rabbit = {
  jumps: true
};

rabbit.__proto__ = animal; // sets rabbit.[[Prototype]] = animal
  • new objects can be created using constructor function, like new F()
  • If F.prototype is an object, then the new operator uses it to set [[Prototype]] for the new object.
  • Please note that F.prototype here means a regular property named "prototype" on F. It sounds something similar to the term “prototype”, but here we really mean a regular property with this name.
let animal = {
  eats: true
};

function Rabbit(name) {
  this.name = name;
}

Rabbit.prototype = animal;

let rabbit = new Rabbit("White Rabbit"); //  rabbit.__proto__ == animal

alert( rabbit.eats ); // true
  • Setting Rabbit.prototype = animal literally states the following: "When a new Rabbit is created, assign its [[Prototype]] to animal".
  • the resulting pic as below:
  • On the picture, "prototype" is a horizontal arrow, meaning a regular property, and [[Prototype]] is vertical, meaning the inheritance of rabbit from animal.

what Hapeend behind the scene when object is created using object literal

  • object literal is a syntax to create an object.
  • when we create an object using object literal syntax js engine will create a object and link it to our newly created object via [[Prototype]] property.

what is [[Prototype]] property?

  • [[Prototype]] property is a special property of an object that contains the methods and properties of the object.
  • [[Prototype]] is itself an object.
  • [[Prototype]] is used to create new objects.
  • [[Prototype]] is set by the constructor function. -[[Prototype]] is hidden when we create an object using object literal syntax. -[[Prototype]] is not hidden when we create an object using new operator.



⬆ Return to top

12. Async Javascript

tick 12.1 What is Asynchrony/asynchronous programming in JS

"Asynchrony" or "asynchronous programming" in JavaScript refers to the ability of the code to run non-blocking operations and continue with other tasks while waiting for the results of those operations. This approach allows the code to be more efficient and responsive, especially when dealing with time-consuming or network-dependent tasks.

📚 Explore: Asynchrony

tick 12.2 What do you mean by synchronous code in javascript

In JavaScript, synchronous code refers to the code that is executed in a sequential manner, one instruction after another. This means that the code is executed in a blocking manner, i.e., the execution of the code blocks the execution of the rest of the code until the current instruction is complete.

📚 Explore: synchronous code

tick 12.3 What do you mean by asynchronous code in javascript

Asynchronous code in JavaScript allows the program to execute tasks concurrently, without blocking the execution of other tasks. This means that the program can continue to run while it waits for some operation to complete, such as fetching data from a server, reading or writing to a file, or waiting for a user input.

📚 Explore: asynchronous code

tick 12.4 What is the diffrence between synchrnous js and async js

In synchronous JavaScript, the program executes code in a single thread, where each line of code is executed one after the other, blocking the execution of other code until the current task is complete. This means that the program must wait for each task to complete before moving on to the next one.

Asynchronous JavaScript allows for more efficient and responsive programs, as it enables the program to execute multiple tasks at the same time without blocking the execution of other code. However, it can also be more complex and difficult to read and write than synchronous code, due to the use of callbacks, promises, and async/await syntax.

📚 Explore: scope

tick 12.5 What is the benefit of async js compare and explain

asynchronous programming is an important tool for modern web development, and can help developers create faster, more responsive, and more efficient web applications. However, it can also be more complex and difficult to work with than synchronous programming, and requires a good understanding of asynchronous programming concepts and techniques.

Improve performance: more responsive user interface better resource utilization simplified code compatibility with external APIs

📚 Explore: scope

Async javascript

async js is all about now and later concept

side effects waiting for user input requesting data from databse requesting data from filesystem sending data across newtwork and waiting for response performing a repeatitive task atfix interval of time


⬆ Return to top

callback functions

a callback function is a function that is passed as an argument to another function and is called by that function when a certain event occurs or a certain task is completed. Callback functions are used to allow asynchronous programming, where a task is initiated, and the program continues to run while waiting for the task to complete.


⬆ Return to top

promise

a Promise is an object that represents a value that may not be available yet but will be resolved in the future, possibly asynchronously. It is a way to handle asynchronous operations such as network requests or database queries that may take some time to complete. A Promise can be in one of three states:

Pending - The initial state when the Promise is created and the value is not yet available.

Fulfilled - The state when the Promise is resolved successfully with a value.

Rejected - The state when the Promise is rejected with an error.

Promises are a way to handle asynchronous code in a more readable and manageable way, by chaining multiple operations together and handling success and error cases separately. The Promise API provides methods to attach callbacks to be executed when the Promise is resolved or rejected, and to chain multiple Promises together to form a sequence of operations.

function synchronousTask() {
  console.log("Synchronous task started");

  return new Promise((resolve, reject) => {
    console.log("Promise created");

    // Resolve the Promise immediately
    resolve("Promise resolved");
  });
}

console.log("Before calling synchronousTask");

synchronousTask().then((result) => {
  console.log("Promise resolved with result:", result);
});

console.log("After calling synchronousTask");

note

can we use promise in synchornous task?

Yes, we can use a Promise in a synchronous task, but it wouldn't make much sense since Promises are primarily designed for handling asynchronous operations.

When we use a Promise in a synchronous task, the code block is still executed synchronously, and the Promise is resolved immediately. This means that the code waiting for the Promise to resolve will not be blocked since the Promise is already resolved.

However, using Promises in synchronous tasks can be useful in some cases, such as when we want to mimic an asynchronous operation or when we want to use the same error handling mechanism for both synchronous and asynchronous code.

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully!');
    }, 2000);
  });
}

const data = fetchData();
console.log(data);
console.log('Code execution continues...');

output

Promise { } Code execution continues...

  1. We define a function called fetchData() that returns a new Promise.

  2. In the Promise constructor, we use setTimeout() to simulate an asynchronous operation that takes 2 seconds to complete.

  3. Once the operation is complete, we call the resolve() function and pass in a message to indicate that the data has been fetched successfully.

  4. We store the Promise returned by fetchData() in a variable called data.

  5. We log the value of data to the console. Since the Promise has not yet resolved, this will log a Promise object rather than the data itself.

  6. We log a message to indicate that code execution continues.

13. Callbacks

tick 13.1 What is callback function

A callback function is a function that is passed as an argument to another function and is executed or called back at some point inside the outer function. The purpose of a callback function is to allow code to be executed after an operation is completed, often asynchronously. The outer function that accepts the callback function as an argument can then invoke or call the callback function at an appropriate time, passing in any necessary parameters as arguments. This allows for greater flexibility and modularity in programming, as different callback functions can be used with the same outer function to achieve different results.

📚 Explore: callback function

tick 13.2 What is the drawback of callback function

While callback functions are a powerful and widely used feature in JavaScript, they have some potential drawbacks that can make them hard to work with in certain situations. Here are some of the drawbacks of callback functions:

Callback hell: When using multiple nested callbacks, the code can quickly become hard to read and maintain, leading to a problem called "callback hell". getData(function(data) { getMoreData(data, function(moreData) { getEvenMoreData(moreData, function(evenMoreData) { // ... }); }); }); Error handling: When an error occurs in a callback function, it can be difficult to handle it properly, especially when there are multiple nested callbacks. Errors can also be easily missed or ignored, leading to unexpected behavior. For example: getData(function(data) { // ... }, function(error) { // ... }); Lack of composition: It can be difficult to compose and combine callback functions, especially when they have different argument and return types. This can make it hard to write modular and reusable code.

Difficulty in managing asynchronous operations: Callback functions can be difficult to use for managing complex asynchronous operations, such as handling multiple requests in parallel, chaining requests together, or handling errors and retries.

📚 Explore: drawbacks of callback

⬆ Return to top

14. Promises

tick 14.1 What is promise

In JavaScript, a promise is an object representing the eventual completion or failure of an asynchronous operation and its resulting value.

📚 Explore: promise

tick 14.2 What is the drawback of promise

While promises provide a powerful and flexible way to handle asynchronous operations in JavaScript, they also have some drawbacks that can make them challenging to work with in certain situations. Here are a few potential drawbacks of using promises in JavaScript.

  1. No cancellation support: Promises are designed to represent the eventual outcome of an asynchronous operation and do not support cancellation. Once a promise is created, it will eventually either be fulfilled or rejected, and there's no way to cancel the operation midway through.

  2. Error handling can be tricky: While promises make it easy to handle asynchronous errors using their catch() method, they can also be tricky to work with when you have multiple promises chained together. It's easy to accidentally swallow errors or end up with unhandled rejections if you're not careful.

  3. Not all APIs are promise-based: While many modern JavaScript APIs and libraries use promises, not all of them do. This can lead to awkward situations where you need to convert between promises and other async patterns, such as callbacks or event emitters.

  4. Debugging can be challenging: Because promises are designed to be used with asynchronous operations, they can be challenging to debug when something goes wrong. Errors that occur inside a promise chain can be difficult to trace back to their source, especially if the chain is long and complex.

Despite these drawbacks, promises remain one of the most powerful and widely used tools for handling asynchronous operations in JavaScript. With a little care and attention, they can be an excellent way to write clean, maintainable, and robust code

📚 Explore: promise drawbacks

tick 14.3 promise methods

Promise methods are used to create, manipulate, and handle Promises in a more efficient and concise way. some of the method are as follows

  1. Promise.all()
  2. Promise.race()
  3. Promise.any()

📚 Explore: promise methods

⬆ Return to top

15. Async Await

tick 15.1 what is async await combination

Async/await is a feature in JavaScript that allows you to write asynchronous code that looks and behaves like synchronous code. It was introduced in ES2017 and has quickly become a popular way to handle asynchronous operations in JavaScript.

Asynchronous code is code that doesn't run immediately, but instead, it runs in the background while other parts of the program continue to execute. The traditional way to handle asynchronous code in JavaScript is to use callbacks or promises, but async/await provides a more intuitive and readable syntax.

The async keyword is used to define a function that contains asynchronous code. The await keyword is used to pause the execution of a function until an asynchronous operation is completed. When the asynchronous operation is complete, the await keyword returns the result of the operation, allowing the function to continue executing.

Here is an example of how to use async/await to make an API call using the fetch function:

async function getData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  console.log(data);
}

In this example, the fetch function returns a promise that resolves to a Response object. We use the await keyword to pause the execution of the function until the promise is resolved. We then call the json method on the Response object to get the data from the response, and again use the await keyword to pause the execution of the function until the data is retrieved.

Async/await makes it easier to write and understand asynchronous code in JavaScript, especially when dealing with complex, nested operations. However, it's important to remember that async/await only works with functions that return promises, and it's still important to handle errors appropriately

📚 Explore: async await combination

tick 15.2 what is the benefit to use async await

text 📚 Explore: benefit async await

⬆ Return to top

async and await




⬆ Return to top

There are many asynchronous operations that can be performed in JavaScript, some of the most common ones are:

Network requests - Fetching data from an API or server using the fetch method or other network libraries.

Database queries - Performing operations on a database, such as querying data or inserting records using libraries like mongoose or sequelize.

Timers - Delaying the execution of a function or code block using the setTimeout or setInterval methods.

File I/O - Reading or writing files on the server or client-side using libraries like fs or blob.

Event listeners - Listening for events such as clicks, scrolls, or keyboard inputs using methods like addEventListener.

Promises - Asynchronous code that returns a Promise, such as fetch or database queries.

Animations - Animating elements on a web page using libraries like GSAP or anime.js.

synchoronous vs asynchronous operation in js

In JavaScript, a synchronous operation is a task that blocks the execution of further code until it is completed. This means that the program waits for the operation to finish before moving on to the next line of code.

An asynchronous operation, on the other hand, is a task that can be initiated and run in the background while the rest of the program continues to execute. This means that the program does not wait for the operation to complete before moving on to the next line of code. Instead, the result of the operation is returned via a callback function or a Promise object at a later time.

Asynchronous operations are often used to handle tasks that take a long time to complete, such as making network requests or performing complex calculations. By running these tasks asynchronously, the program can continue to execute other code while the task is being processed, leading to a more responsive and efficient application.

Example of a synchronous operation:

// Synchronous operation: blocking the main thread
function sum(a, b) {
  return a + b;
}

console.log("Before sum");
const result = sum(2, 3);
console.log("After sum");
console.log(result);

In the above example, the sum() function is a synchronous operation because it is executed in a blocking manner, which means the execution of the program is paused until the function completes. In this case, the console.log("After sum") statement is not executed until the sum() function returns and the result variable is assigned the returned value.

Example of an asynchronous operation:

// Asynchronous operation: non-blocking the main thread
console.log("Before setTimeout");
setTimeout(() => {
  console.log("Inside setTimeout");
}, 1000);
console.log("After setTimeout");

In the above example, the setTimeout() function is an asynchronous operation because it is executed in a non-blocking manner, which means the execution of the program is not paused and the next statement is executed immediately after calling the setTimeout() function. In this case, the console.log("After setTimeout") statement is executed immediately after calling the setTimeout() function, and the callback function passed to setTimeout() is executed asynchronously after a delay of one second. This allows other operations to continue executing in the meantime, making the program more efficient.




⬆ Return to top

explainjs's People

Contributors

pvm-77 avatar

Stargazers

Md Mohib Khan avatar

Watchers

 avatar

Forkers

mdmohibkhan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.