JAVASCRIPT Technical Paper
Tags: webdev, javascript, programming, beginners
Published: 2023-05-29 10:59:40


JavaScript is a high-level, interpreted programming language primarily used for creating dynamic and interactive web pages.
### Loop
- **for** :- The `for` loop is a traditional loop structure that repeats a block of code a specific number of times. It consists of three parts: initialization, condition, and increment/decrement.
example:-
	```
	for (let i = 0; i < 5; i++) {
	  console.log(i);
	}
	```
- **forEach** :- The `forEach` loop is a method available on arrays that iterates over each element and executes a callback function for each element.
example:-
	```
	const numbers = [1, 2, 3, 4, 5];
	numbers.forEach(function(number) {
	  console.log(number);
	});
	```
- **for..in** :- The `for...in` loop iterates over the properties of an object. It allows you to loop through the enumerable properties of an object.
example:-
	```
	const person = {
  name: "John",
  age: 30,
  city: "New York"
	};
	for (let key in person) {
	  console.log(key + ": " + person[key]);
	}
	```
- **for..of** :- The `for...of` loop iterates over iterable objects, such as arrays or strings. It allows you to loop through each element of the iterable.
example:-
	```
	const colors = ["red", "green", "blue"];
	for (let color of colors) {
	  console.log(color);
	}
	```
- **while** :- The `while` loop executes a block of code repeatedly as long as a specified condition is true. It does not require an explicit counter.
- example:-
	```
	let i = 0;
	while (i < 5) {
	  console.log(i);
	  i++;
	}
	```

###   Mutable and Immutable Methods (in strings and arrays)
 Mutable methods modify the original string or array.  Immutable methods return a new string or array, leaving the original unchanged.
- **Strings**:
-  Mutable Methods:

	-   `concat`: Concatenates two or more strings and returns a new string.
	-   `slice`: Extracts a portion of the string and returns a new string.
	-   `replace`: Replaces specified substring(s) with a new substring and returns a new string.
	-   `toUpperCase` and `toLowerCase`: Converts the case of the string and returns a new string.
	-   `trim` and other trimming methods: Removes whitespace characters from the string and returns a new string.

- Immutable Methods:

	-   `charAt` and `charCodeAt`: Accesses a character or its Unicode value at a specified index.
	-   `substring` and `substr`: Extracts a substring from the original string.
	-   `indexOf` and `lastIndexOf`: Searches for a substring within the string and returns its index.
- **Array**
- Mutable Methods:

	-   `push` and `pop`: Add and remove elements from the end of an array.
	-   `shift` and `unshift`: Add and remove elements from the beginning of an array.
	-   `splice`: Modifies an array by adding, removing, or replacing elements at specified positions.
	-   `reverse`: Reverses the order of elements in an array.
	-   `sort`: Sorts the elements of an array in place.
- Immutable Methods:

	-   `concat`: Concatenates two or more arrays and returns a new array.
	-   `slice`: Extracts a portion of an array and returns a new array.
	-   `filter`: Creates a new array with elements that satisfy a filtering condition.
	-   `map`: Creates a new array by applying a transformation function to each element.

###    Pass by Reference and Pass by Value 
It provides an in-depth analysis of how JavaScript handles variable assignment and function parameter passing.
- **Pass by Value**:

-   In pass by value, a copy of the value is passed to a function or assigned to a new variable.
-   Changes made to the copied value do not affect the original value.
-   Primitive data types (numbers, booleans, strings) are passed by value in JavaScript.
-   Example:
	```
	let num = 10;

	function increment(num) {
	  num += 1;
	  console.log(num); // Output: 11
	}

	increment(num);
	console.log(num); // Output: 10
	```
- **Pass by Reference**:

-   In pass by reference, a reference to the original value is passed to a function or assigned to a new variable.
-   Changes made to the referenced value affect the original value.
-   Objects and arrays are passed by reference in JavaScript.
-   Example:
	```
		let arr = [1, 2, 3];

	function modifyArray(arr) {
	  arr.push(4);
	  console.log(arr); // Output: [1, 2, 3, 4]
	}

	modifyArray(arr);
	console.log(arr); // Output: [1, 2, 3, 4]
	```
### Array Methods:
- **Basics**
	-    Array.pop
	
		The `pop` method removes the last element from an array and returns that element.

	```
	const fruits = ["apple", "banana", "orange"];
	const removedFruit = fruits.pop();
	console.log(fruits); // Output: ["apple", "banana"]
	console.log(removedFruit); // Output: "orange"
	```

	-   Array.push
	
		The `push` method adds one or more elements to the end of an array and returns the new length of the array.
	```
		const fruits = ["apple", "banana"];
		const newLength = fruits.push("orange", "grape");
		console.log(fruits); // Output: ["apple", "banana",   "orange", "grape"]
		console.log(newLength); // Output: 4
	```

	-   Array.concat

		The `concat` method combines two or more arrays and returns a new array.
	```
	const arr1 = [1, 2, 3];
	const arr2 = [4, 5];
	const combinedArray = arr1.concat(arr2);
	console.log(combinedArray); // Output: [1, 2, 3, 4, 5]

	```
	-   Array.slice
	
		The `slice` method extracts a portion of an array into a new array.
	```
	const numbers = [1, 2, 3, 4, 5];
	const slicedArray = numbers.slice(1, 4);
	console.log(slicedArray); // Output: [2, 3, 4]

	```
	-   Array.splice
	
		The `splice` method changes the content of an array by removing, replacing, or adding elements.
	```
	const numbers = [1, 2, 3, 4, 5];
	const removedElements = numbers.splice(2, 2, 6, 7);
	console.log(numbers); // Output: [1, 2, 6, 7, 5]
	console.log(removedElements); // Output: [3, 4]

	```
	-   Array.join
	
		The `join` method combines all elements of an array into a string.
	```
	const fruits = ["apple", "banana", "orange"];
	const joinedString = fruits.join(", ");
	console.log(joinedString); // Output: "apple, banana, orange"

	```
	-   Array.flat
	
		The `flat` method creates a new array with all sub-array elements concatenated recursively up to the specified depth.
	```
	const nestedArray = [1, 2, [3, 4, [5, 6]]];
	const flattenedArray = nestedArray.flat(2);
	console.log(flattenedArray); // Output: [1, 2, 3, 4, 5,]

	```
- **Findings**
	- Array.find:

		 The `find` method returns the first element in an array that satisfies a provided testing function.If a matching element is found, `find` returns the element itself; otherwise, it returns `undefined`.
 Example:
		 ```
	    
	    `	const numbers = [1, 2, 3, 4, 5];
	    const foundNumber = numbers.find((num) => num > 3);
	    console.log(foundNumber); // Output: 4` 
	    ```
	    

	- Array.indexOf:


		The `indexOf` method returns the first index at which a specified element is found in an array.
 If the element is not found, it returns -1.
Example:
		 ```
	    const fruits = ["apple", "banana", "orange"];
		const index = fruits.indexOf("banana");
		console.log(index); // Output: 1` 
		```
	    

	- Array.includes:

		The `includes` method determines whether an array includes a certain element, returning a boolean value.
  Example:
	     ```
	    `const numbers = [1, 2, 3, 4, 5];
	    const includesThree = numbers.includes(3);
	    console.log(includesThree); // Output: true` 
	    ```
	    

	- Array.findIndex:

		The `findIndex` method returns the index of the first element in an array that satisfies a provided testing function.
Example:
	```
	    
	    `const numbers = [1, 2, 3, 4, 5];
	    const index = numbers.findIndex((num) => num > 3);
	    console.log(index); // Output: 3` 
	    ```
- **Higher Order Function**
	- Array.forEach:

	 The `forEach` method executes a provided callback function once for each element in an array.
  The callback function takes three arguments: the current element, the index, and the array itself.
	 Example:
	    
	    `const numbers = [1, 2, 3, 4, 5];
	    numbers.forEach((num) => {
	      console.log(num * 2);
	    });
	    // Output:
	    // 2
	    // 4
	    // 6
	    // 8
	    // 10` 
	    

	- Array.filter:

	 
		 The `filter` method creates a new array with all elements that pass a provided filtering function.
	 The filtering function takes three arguments: the current element, the index, and the array itself.
	  Example:
		```
			  `const numbers = [1, 2, 3, 4, 5];
		    const evenNumbers = numbers.filter((num) => num % 2 ===  0);
		    console.log(evenNumbers); // Output: [2, 4]` 
	    
		 ```

	- Array.map:

		
		 The `map` method creates a new array with the results of calling a provided function on every element in the array.
    The mapping function takes three arguments: the current element, the index, and the array itself.
	Example:
	    
	    ```
	    `const numbers = [1, 2, 3, 4, 5];
	    const doubledNumbers = numbers.map((num) => num * 2);
	    console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]` 
	    ```
	    

	- Array.reduce:

		 
		The `reduce` method applies a provided function to reduce the array to a single value.
	The reducing function takes four arguments: the accumulator, the current element, the index, and the array itself.
	 Example:
	  ```
	    `const numbers = [1, 2, 3, 4, 5];
	    const sum = numbers.reduce((accumulator, num) => accumulator + num, 0);
	    console.log(sum); // Output: 15` 
	    ```
	    

	- Array.sort:

		 The `sort` method sorts the elements of an array in place and returns the sorted array.
	  Example:
	    ```
	    `const fruits = ["banana", "apple", "orange"];
	    fruits.sort();
	    console.log(fruits); // Output: ["apple", "banana", "orange"]`
	    ```
	    
- **Advance**
	-    Array methods chaining
	
		By chaining array methods, the output of one method becomes the input for the next method in the chain. This allows you to perform multiple operations on an array in a single statement.

	```
	const numbers = [1, 2, 3, 4, 5];

	const result = numbers
	  .filter(num => num % 2 === 0)  // Filter even numbers
	  .map(num => num * 2)           // Double each number
	  .reduce((sum, num) => sum + num, 0);  // Calculate the sum

	console.log(result);  // 18
	```
### String Methods
Mutable Methods (Modify the original string):

-   `concat`: Concatenates one or more strings with the original string and returns a new string.
-   `slice`: Extracts a portion of the string into a new string based on the specified indices.
-   `splice`: Changes the content of the string by adding, removing, or replacing characters.
-   `replaceAll`: Replaces all occurrences of a specified substring with another substring.
-   `toUpperCase`: Converts the string to uppercase characters.
-   `toLowerCase`: Converts the string to lowercase characters.
Example:-
	```
	let char = str.charAt(0);
	console.log(char); // Output: "H"

	let substring = str.substring(0, 5);
	console.log(substring); // Output: "Hello"

	let replacedFirstOccurrence = str.replace("o", "x");
	console.log(replacedFirstOccurrence); // Output: "Hxllo World"

	let splittedArray = str.split(" ");
	console.log(splittedArray); // Output: ["Hello", "World"]

	let trimmedStr = str.trim();
	console.log(trimmedStr); // Output: "Hello World"

	let startsWithHello = str.startsWith("Hello");
	console.log(startsWithHello); // Output: true

	let endsWithWorld = str.endsWith("World");
	console.log(endsWithWorld); // Output: true

	```

Immutable Methods (Create a new string without modifying the original string):

-   `charAt`: Returns the character at a specified index in the string.
-   `substring`: Extracts a portion of the string into a new string based on the specified indices.
-   `replace`: Replaces the first occurrence of a specified substring with another substring.
-   `split`: Splits the string into an array of substrings based on a specified delimiter.
-   `trim`: Removes whitespace from both ends of the string.
-   `startsWith`: Checks if the string starts with a specified substring.
-   `endsWith`: Checks if the string ends with a specified substring.
Example:-
    ```
    let char = str.charAt(0);
	console.log(char); // Output: "H"

	let substring = str.substring(0, 5);
	console.log(substring); // Output: "Hello"

	let replacedFirstOccurrence = str.replace("o", "x");
	console.log(replacedFirstOccurrence); // Output: "Hxllo World"

	let splittedArray = str.split(" ");
	console.log(splittedArray); // Output: ["Hello", "World"]

	let trimmedStr = str.trim();
	console.log(trimmedStr); // Output: "Hello World"

	let startsWithHello = str.startsWith("Hello");
	console.log(startsWithHello); // Output: true

	let endsWithWorld = str.endsWith("World");
	console.log(endsWithWorld); // Output: true

    ```
### Object Methods and Opertions
1.  Adding or Modifying Key-Value Pairs:
    
   -   `object[key] = value`: Assigns a value to a specific key in the object. If the key already exists, the value will be updated; otherwise, a new key-value pair will be added.
2.  Accessing Values:
    
   -   `object[key]`: Retrieves the value associated with a specific key from the object.
    
3.  Checking for Key Existence:
    
   -   `key in object`: Returns `true` if the object contains the specified key; otherwise, returns `false`.
    -   `object.hasOwnProperty(key)`: Returns `true` if the object directly contains the specified key (ignores keys from the prototype chain); otherwise, returns `false`.
4.  Removing Key-Value Pairs:
    
   -   `delete object[key]`: Removes the key-value pair associated with the specified key from the object.
5.  Getting All Keys:
    
   -   `Object.keys(object)`: Returns an array containing all the keys of the object.
6.  Getting All Values:
    
   -   `Object.values(object)`: Returns an array containing all the values of the object.
7.  Getting Key-Value Pairs as Arrays:
    
   -   `Object.entries(object)`: Returns an array of key-value pairs, where each pair is represented as an array `[key, value]`.
    Example:-
	    ```
	    const hashmap = {};

		// Adding key-value pairs
		hashmap["name"] = "John";
		hashmap["age"] = 30;
		hashmap["city"] = "New York";

		// Accessing values
		console.log(hashmap["name"]); // Output: John

		// Checking for key existence
		console.log("age" in hashmap); // Output: true
		console.log(hashmap.hasOwnProperty("gender")); // Output: false

		// Removing key-value pair
		delete hashmap["city"];

		// Getting all keys
		const keys = Object.keys(hashmap);
		console.log(keys); // Output: ['name', 'age']

		// Getting all values
		const values = Object.values(hashmap);
		console.log(values); // Output: ['John', 30]

		// Getting key-value pairs as arrays
		const entries = Object.entries(hashmap);
		console.log(entries); // Output: [['name', 'John'], ['age', 30]]

	   ```
### Hoisting
Hoisting is a mechanism in JavaScript that allows variable and function declarations to be moved to the top of their respective scopes during the compilation phase, before the code is executed.
-   Only function declarations and variable declarations using `var` are hoisted.
-   Variables declared with `let` and `const` are not hoisted.
Example:-
	```
	console.log(x); // Output: undefined
	var x = 10;
	console.log(x); // Output: 10

	```

### Scopes
Scopes in JavaScript determine the accessibility and visibility of variables, functions, and objects within your code. JavaScript has three main types of scopes:

1.  Global Scope:
    
   -   The global scope is the outermost scope in JavaScript.
   -   Variables declared in the global scope are accessible throughout the entire codebase, including within functions and other scopes.
   -   Example:
	      ```
	       var globalVariable = "I'm in the global scope";
        
        function globalFunction() {
          console.log(globalVariable); // Output: "I'm in the 			global scope"
        }
        
        globalFunction();` 
	      ```
        
2.  Function Scope:
    
   -   Each function in JavaScript creates its own scope, known as the function scope.
   -   Variables declared within a function are only accessible within that function and any nested functions.
   -   Example:
	      ```
	        
	        `function outerFunction() {
	          var outerVariable = "I'm in the outer function";
	        
	          function innerFunction() {
	            console.log(outerVariable); // Output: "I'm in the outer function"
	          }
	        
	          innerFunction();
	        }
	        
	        outerFunction();`
	      ``` 
        
3.  Block Scope (Introduced in ES6):
    
   -   Block scope is created by curly braces (`{}`) in statements such as `if`, `for`, `while`, and `let`/`const` variable declarations.
   -   Variables declared with `let` and `const` are block-scoped and are only accessible within the block where they are defined.
   -   Example:
	      ```
	        `function blockScopeExample() {
	          if (true) {
	            let blockVariable = "I'm in the block scope";
	            console.log(blockVariable); // Output: "I'm in the block scope"
	          }
	        
	          console.log(blockVariable); // Output: ReferenceError: blockVariable is not defined
	        }
	        
	        blockScopeExample();`
	      ```
### Closures
A closure is a function along with its preserved lexical environment.
Here are some key points about closures:

1.  Definition:
    
   -   A closure is created when a nested function (inner function) accesses variables from its outer function, even after the outer function has completed execution.
   -   The inner function "closes over" the variables it references, hence the term "closure".
2.  Lexical Scope:
    
   -   Closures rely on lexical scoping, which means that functions are executed using the variable scope they were defined in.
   -   The inner function has access to the variables in its own scope, the scope of the outer function, and the global scope.
3.  Preserved Environment:
    
   -   Closures preserve the variables and their values at the time of creation, allowing the inner function to access and manipulate them even outside of the original scope.
   -   This allows for data encapsulation and private variables in JavaScript.
Examples
	```
		function outerFunction() {
		  var outerVariable = 'I am from the outer function';

		  function innerFunction() {
		    console.log(outerVariable); // Accesses outerVariable from the outer function's scope
		  }

		  return innerFunction;
			}

			var closure = outerFunction(); // Assigns the inner function to the closure variable
			closure(); // Invokes the inner function, which logs "I am from the outer function"

	```
### Higher Order Functions
-   Higher-order functions can accept other functions as parameters.
-   The passed function is often referred to as a "callback" function.
-   This allows for the implementation of customizable behavior or logic.
-   Example:
	```
	function higherOrder(callback) {
	  callback();
	}

	function callbackFunction() {
	  console.log("I'm a callback function");
	}

	higherOrder(callbackFunction); // Outputs: "I'm a callback function"

	```

### References
[GFG](https://www.geeksforgeeks.org/javascript/)
[W3SCHOOL](https://www.w3schools.com/js/js_object_definition.asp)