JavaScript
Published: 2023-05-30 12:41:23

## 1.Loops :  
  
In JavaScript, there are several types of loops that you can use to repeat a block of code multiple times. Here are the main types of loops in JavaScript:
1.**for loop**: The `for` loop is a widely used loop that allows you to repeat a block of code for a specified number of times. It consists of an initialization, a condition, an increment or decrement statement, and the code block to be executed.

Syntax:
```
for (initialization; condition; increment/decrement) {
  // code to be executed
}
```
Example:
```
for (let i = 0; i < 5; i++) {
  console.log(i);
}
```

2.**while loop**: The `while` loop repeats a block of code as long as a specified condition is true. It only has a condition, and the code block is executed repeatedly until the condition becomes false.
Syntax:
```
while (condition) {
  // code to be executed
}
```
Example:
```
let i = 0;
while (i < 5) {
  console.log(i);
  i++;
}
```

3.**for...in loop**: The `for...in` loop is used to iterate over the properties of an object. It allows you to access each property of an object and perform some action.
Syntax:
```
for (variable in object) {
  // code to be executed
}
```
Example:
```
const person = {
  name: 'John',
  age: 30,
  city: 'New York',
};

for (let key in person) {
  console.log(key + ': ' + person[key]);
}

```

4.**for...of loop**: The `for...of` loop was introduced in ES6 and is used to iterate over iterable objects, such as arrays, strings, and NodeLists. It allows you to access each element of the iterable object.
Syntax: 
```
for (variable of iterable) {
  // code to be executed
}
```
Example:
 ```
const colors = ['red', 'green', 'blue'];

for (let color of colors) {
  console.log(color);
}
``` 

5.**forEach loop**: It is a method available on arrays that allows you to iterate over each element of the array and perform a specified action or function on each element. It provides a more concise and expressive way to iterate through arrays compared to traditional `for` or `while` loops.
syntax:
```
array.forEach(function(currentValue, index, array) {
  // code to be executed on each element
});
```
Example:
```
const numbers = [1, 2, 3, 4, 5];

numbers.forEach(function(number) {
  console.log(number);
});

//Output:
1
2
3
4
5
```

## 2.Mutable & immutable methods (in strings and in arrays) :
  
In JavaScript, objects can have both mutable and immutable methods. Let's break down what each of these means:  
  
### Mutable methods:  
Mutable methods are methods that can modify the object they are called on. They directly change the state of the object by modifying its properties or internal data. These methods typically have side effects and may alter the object's content. Some examples of mutable methods in JavaScript are push(), pop(), splice(), and sort() for arrays. When you call these methods, the original array is modified.  
  
  
### Immutable methods:-  
mmutable methods, on the other hand, do not modify the object they are called on. Instead, they return a new object or value that reflects the desired change, leaving the original object unchanged. Immutable methods are non-destructive and are often used in functional programming paradigms. Examples of immutable methods in JavaScript include map(), filter(), and concat() for arrays.  
  
Here are some examples of mutable and immutable methods for strings and arrays in JavaScript:  
  
**Mutable String Methods:**
1. `concat()`: Joins two or more strings and returns a new string.  
2. `toUpperCase()`: Converts the string to uppercase in place.  
3. `toLowerCase()`: Converts the string to lowercase in place.  
4. `slice()`: Extracts a portion of the string and returns a new string.  
  
**Immutable String Methods:**
1. `toUpperCase()`: Returns a new string with the uppercase conversion.  
2. `toLowerCase()`: Returns a new string with the lowercase conversion.  
3. `slice()`: Returns a new string with a portion of the original string.  
  
**Mutable Array Methods:**
1. `push()`: Adds one or more elements to the end of an array and returns the new length.  
2. `pop()`: Removes the last element from an array and returns that element.  
3. `splice()`: Changes the content of an array by adding or removing elements.  
  
**Immutable Array Methods:**
1. `concat()`: Returns a new array that combines two or more arrays.  
2. `slice()`: Returns a new array with a portion of the original array.  
3. `filter()`: Returns a new array with elements that pass a specific condition.  
  
It's important to note that the distinction between mutable and immutable methods is not always strict in JavaScript. Some methods may exhibit both mutable and immutable behavior depending on how they are used. Additionally, there are also methods like `sort()` and `reverse()` that modify the original array in place, making them mutable methods.  
  
## 3.pass by reference & pass by value :
  
In JavaScript, the concept of pass by reference and pass by value depends on the type of data being passed as an argument to a function.  
  
**Pass by Value:**
When you pass a primitive data type (such as numbers, strings, or booleans) to a function, it is passed by value. It means that a copy of the value is created and assigned to a new variable within the function. Any changes made to this new variable will not affect the original value outside the function.

Example:
```
function updateValue(value)  
{
value = 42; // Updating the value inside the function  
}
let num = 10;  
updateValue(num);  
console.log(num);  

Output: 10  
```

In this example, the `num` variable is passed by value to the `updateValue` function. Even though the function assigns a new value of 42 to the `value` parameter, it does not affect the original `num` variable because it is a copy.

**Pass by Reference:**
When you pass an object (including arrays and functions) to a function, it is passed by reference. It means that the memory address of the object is passed, rather than creating a copy of the object. Any modifications made to the object inside the function will affect the original object.

Example:
```
function updateArray(array)
{
array.push(4); // Modifying the array inside the function  
}
let numbers = [1, 2, 3];
updateArray(numbers);
console.log(numbers);

Output: [1, 2, 3, 4]
```

In this example, the `numbers` array is passed by reference to the `updateArray` function. When the function pushes the value 4 into the `array` parameter, it modifies the original `numbers` array as well.  

It's important to note that even though objects are passed by reference, reassigning the entire object within the function will not affect the original object outside the function. It only affects the local variable referencing that object.

Example:
```
function updateObject(obj)
{
obj = { name: 'John' }; // Reassigning the object inside the function
}
let person = { name: 'Alice' };
updateObject(person);
console.log(person);

Output: { name: 'Alice' }
```

In this case, the `obj` parameter inside the function is reassigned to a new object, but it doesn't modify the original `person` object. The local `obj` variable now points to a different memory location.

  
## 4.Array methods :
  
In JavaScript, arrays have several built-in methods that can be used to modify the array directly. These methods are referred to as mutable array methods because they modify the original array rather than creating a new array. Here are some commonly used mutable array methods:  
  
1.push: The `push` method adds one or more elements to the end of an array.

Example:-
```
const numbers = [1, 2, 3];
numbers.push(4, 5);
console.log(numbers);

Output: [1, 2, 3, 4, 5]
```

2.pop: The `pop` method removes the last element from an array and returns that element.

Example:-
```
const numbers = [1, 2, 3, 4, 5];
const lastElement = numbers.pop();
console.log(lastElement);
console.log(numbers);

Output: 5  
[1, 2, 3, 4]
```

3.shift: The `shift` method removes the first element from an array and returns that element. It also shifts all the remaining elements to a lower index.

Example:-
```
const numbers = [1, 2, 3, 4, 5];
const firstElement = numbers.shift();
console.log(firstElement);
console.log(numbers);

Output: 1
[2, 3, 4, 5]
```
4.unshift: The `unshift` method adds one or more elements to the beginning of an array and shifts the existing elements to higher indices.

Example:-  
```
const numbers = [2, 3, 4, 5];
numbers.unshift(1);
console.log(numbers);

Output: [1, 2, 3, 4, 5]
```

5.splice: The `splice` method can be used to add, remove, or replace elements within an array. It modifies the original array and returns the removed elements.

Example:-
```
const numbers = [1, 2, 5, 6];
numbers.splice(2, 0, 3, 4); // Inserts 3 and 4 at index 2
console.log(numbers);
numbers.splice(3, 2); // Removes 2 elements starting from index 3
console.log(numbers);

Output: [1, 2, 3, 4, 5, 6]
[1, 2, 3, 6]
```

These mutable array methods provide convenient ways to modify arrays directly. However, it's important to be cautious when using them as they can alter the original array, potentially affecting other parts of your code.

### 1.Basics :
  
1.push: Adds one or more elements to the end of an array and returns the new length of the array.

Example:-  
```
let array = [1, 2, 3];
array.push(4);
console.log(array);

Output: [1, 2, 3, 4]  
```

2.pop: Removes the last element from an array and returns that element.  
  
Example:-  
```
let array = [1, 2, 3];  
let lastElement = array.pop();  
console.log(lastElement); // Output: 3  
console.log(array);  
  
Output: [1, 2]  
  ```

3.concat: Concatenates two or more arrays and returns a new array.  
  
Example:-  
```
let arr1 = [1, 2, 3];  
let arr2 = [4, 5];  
let newArr = arr1.concat(arr2);  
console.log(newArr);  
  
Output: [1, 2, 3, 4, 5]  
  ```
4.Slice :-  
  
(i) slice using an array : Extracts a portion of an array and returns a new array without modifying the original array.  
  
Example:-  
```
let arr = [1, 2, 3, 4, 5];  
let newArr = arr.slice(2);  
console.log(newArr);  
  
Output: [3, 4, 5]  
  ```

(ii) slice using an string : Extracts a portion of a string and returns a new string without modifying the original string.  
  
Example:-  
```
let str = 'Hello World';  
let newStr = str.slice(6);  
console.log(newStr);  
  
Output: 'World'  
  ```

5.splice: This method is mutable. Changes the contents of an array by removing, replacing, or adding elements. It modifies the original array  
  
Example:-  
```
let arr = [1, 2, 3, 4, 5];  
arr.splice(2, 1);  
console.log(arr);  
  
Output: [1, 2, 4, 5]  
  ```

6.join: This method is immutable. It joins all elements of an array into a string, using a specified separator, and returns the resulting string. The original array remains unchanged.  
  
Example:
```
const fruits = ['apple', 'banana', 'orange'];  
const joinedString = fruits.join(', ');  
console.log(joinedString); // Output: 'apple, banana, orange'  
console.log(fruits);  
  
Output: ['apple', 'banana', 'orange']  
  ```

In the example above, `join` returns a new string with all the elements of the `fruits` array joined by `', '`. The original array `fruits` is not modified.

7.flat:
The flat() method is an array method in JavaScript that is used to flatten a nested array by concatenating its subarrays into a new array. It returns a new array with all the elements of the original array and any subarrays concatenated together into a single level.

The flat() method can be invoked on an array and accepts an optional parameter depth, which determines the depth of flattening. By default, depth is set to 1, meaning only the immediate nested arrays are flattened. If a negative value is provided for depth, it will flatten all nested arrays regardless of their depth.
Example:
```
const nestedArray = [1, 2, [3, 4], [5, [6, 7]]];

const flattenedArray = nestedArray.flat();

console.log(flattenedArray);
// Output: [1, 2, 3, 4, 5, [6, 7]]
```
  
### 2.Finding :
  
1.find: The `find` method is used to find the first element in an array that satisfies a given condition. It takes a callback function as an argument and returns the first element for which the callback function returns a truthy value. If no element is found, it returns `undefined`.  
  
Example:
```
const numbers = [1, 2, 3, 4, 5];  
const found = numbers.find((element) => element > 3);  
console.log(found);  
  
Output: 4  
  ```

2.indexOf: The `indexOf` method is used to find the index of the first occurrence of a specified element or value in an array or string. It returns the index of the element if found, and -1 if the element is not present.  
  
Example:  
  ```
const fruits = ['apple', 'banana', 'orange', 'banana'];  
const index = fruits.indexOf('banana');  
console.log(index);  
  
Output: 1  
  ```

3.includes: The `includes` method is used to check whether an array or string contains a specific element or value. It returns `true` if the element is found, and `false` otherwise.  
  
Example:  
  ```
const numbers = [1, 2, 3, 4, 5];  
const includesThree = numbers.includes(3);  
console.log(includesThree);  
  
Output: true  
  ```

4.findIndex: The `findIndex` method is similar to the `find` method, but it returns the index of the first element that satisfies a given condition instead of the element itself. If no element is found, it returns -1.  
  
Example:  
  ```
const numbers = [1, 2, 3, 4, 5];  
const index = numbers.findIndex((element) => element > 3);  
console.log(index);  
  
Output: 3  
  ```

These methods are commonly used in JavaScript to search for elements or values within arrays or strings based on different conditions.  
  
### 3.Higher order functions :
  
Higher-order functions are an important concept in functional programming. They are functions that can take other functions as arguments or return functions as results. In this context, let's explore some common higher-order functions: `forEach`, `filter`, `map`, `reduce`, and `sort`.  
  
1.forEach: The `forEach` function is used to iterate over an array or a collection and apply a function to each element. It doesn't return a new array; instead, it performs an action for each element.  
  
Example :  
  ```
Const numbers = [1, 2, 3, 4];  
numbers.forEach  
( (num) =>  
{  
console.log(num);  
}  
);
```

2.filter: The `filter` function creates a new array containing elements from the original array that satisfy a specified condition defined by a filtering function.  
  
Example:-  
  ```
const numbers = [1, 2, 3, 4];  
const evenNumbers = numbers.filter((num) => num % 2 === 0);  
console.log(evenNumbers);  
  
Output: [2, 4]  
  ```

3.map: The `map` function applies a transformation function to each element of an array and returns a new array containing the transformed elements.  
  
Example:-  
  ```
const numbers = [1, 2, 3, 4];  
const doubledNumbers = numbers.map((num) => num * 2);  
console.log(doubledNumbers); // Output: [2, 4, 6, 8]  
  ```

4.reduce: The `reduce` function takes an array and reduces it to a single value by applying an accumulator function to each element. The accumulator function takes an accumulated value and the current element and returns a new accumulated value.  
  
Example:-  
  ```
const numbers = [1, 2, 3, 4];  
const sum = numbers.reduce((accumulator, num) => accumulator + num, 0);  
console.log(sum);  
  
Output: 10  
  ```

5.sort: The `sort` function is used to sort the elements of an array in place. It takes an optional comparison function that defines the sorting order.  
  
Example:-  
  ```
const numbers = [4, 2, 1, 3];  
numbers.sort((a, b) => a - b);  
console.log(numbers);  
  
Output: [1, 2, 3, 4]  
  ```

These higher-order functions provide powerful tools for working with arrays and collections in a functional programming paradigm, making the code concise and expressive.  
  
### 4.Advanced :
  
Array methods chaining is a technique where multiple array methods are chained together to perform a sequence of operations on an array. Each method in the chain operates on the result of the previous method, allowing you to perform complex transformations and manipulations on arrays in a concise manner.  
  
Example :-  
  ```
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); // Sum all numbers  
console.log(result);  
  
Output: 18  
  ```

In the above example:  
  
1.`filter` is used to filter out even numbers from the original array.  
2.`map` is then used to double each filtered number.  
3.Finally, `reduce` is applied to sum up all the doubled numbers.  
  
By chaining these methods together, you can achieve the desired result in a concise and readable way.  
  
It's important to note that when using method chaining, the order of methods in the chain matters. Each method operates on the result of the previous method, so you need to consider the desired sequence of operations.  
  
Method chaining is a powerful technique that allows you to perform complex array manipulations in a more compact and expressive manner, enhancing code readability and maintainability.
  
## 5.String methods :
  
In JavaScript, strings are immutable, which means that once a string is created, it cannot be changed. However, there are string methods that return a modified version of the original string without directly modifying it. Let's take a look at some of the commonly used string methods in JavaScript:  
  
1.concat(): This method concatenates two or more strings and returns a new string.  
  
Example:-  
```
let str1 = 'Hello';  
let str2 = 'World';  
let result = str1.concat(' ', str2);  
console.log(result);  
  
Output: "Hello World"  
  ```

2.toUpperCase(): Converts the string to uppercase and returns a new string.  
  
Example:-  
```
const str = "hello, world";  
const newString = str.toUpperCase();  
console.log(newString);  
  
Output: "HELLO, WORLD"  
  ```

3.toLowerCase(): Converts the string to lowercase and returns a new string.  
  
Example :-  
```
const str = "HELLO, WORLD";  
const newString = str.toLowerCase();  
console.log(newString);  
  
Output: "hello, world"  
  ```
These methods, along with others, allow you to perform various operations on strings without modifying the original string itself.  
  
4.slice(): This method returns a new string containing a portion of the original string based on the specified start and end indices.  
  
Example:-  
```
let str = 'Hello World';  
let result = str.slice(6, 11);  
console.log(result);  
  
Output: "World"  
  ```

5.replace(): This method returns a new string with all occurrences of a specified substring replaced by another substring.  
  
Example:-  
  ```
let str = 'Hello World';  
let result = str.replace('World', 'Universe');  
console.log(result);  
  
Output: "Hello Universe"  
  ```

6.split(): This method splits a string into an array of substrings based on a specified delimiter and returns the array.  
  
Example :-  
```
str = 'Hello,World';  
let result = str.split(',');  
console.log(result);  
  
Output: ["Hello", "World"]  
  ```

These methods, and many others, allow you to perform various operations on strings while keeping the original string unchanged. Remember that each method returns a new string, so you need to assign the result to a variable if you want to store or use the modified string.
  
## 6.Object methods & operations :
  
In JavaScript, objects are one of the fundamental data types and can have properties and methods associated with them. Methods in JavaScript are functions that are defined as properties of an object. They can be invoked or called to perform certain actions or operations on the object or its data.  
  
1.Defining an Object:  
Objects can be defined using object literals, constructor functions, or ES6 classes.  
  
Example:-  
```
const person =  
{  
name: 'John',  
age: 30,  
greet: function()  
	{  
	    console.log(`Hello, my name is ${[this.name]}`);  
	}  
};  
  ```

2.Accessing Object Properties:  
Object properties can be accessed using dot notation (`object.property`) or bracket notation (`object['property']`).  
  
Example :-  
```
console.log(person['name']);  
console.log(person['age']);  
  
Output: john  
30  
  ```

3.Defining Object Methods:  
Object methods are defined as functions within an object. They can access and modify object properties using the `this` keyword.  
  
Example:-  
```
const person =  
{  
name: 'John',  
age: 30,  
greet: function()  
	{  
		console.log(`Hello, my name is ${[this.name]}`);  
	},  
increaseAge: function()  
	{  
		this.age++;  
	}  
};  
  ```

4.Invoking Object Methods:  
Object methods are invoked by using the dot notation or bracket notation with parentheses.  
  
Example :-  
```
person.greet();  
person.increaseAge();  
console.log(person.age);  
  
Output:  
Hello, my name is John  
31  
  ```

5.The `this` Keyword:  
The `this` keyword refers to the object that the method belongs to. It allows you to access and modify object properties within the method.  
  
6.Shorthand Method Syntax:
ES6 introduced a shorthand syntax for defining object methods using concise method notation.  
  
Example:-  
  ```
const person =  
{  
name: 'John',  
age: 30,  
greet() {  
console.log(`Hello, my name is ${[this.name](http://this.name/)}`);  
},  
increaseAge() {  
this.age++;  
}  
};  
  ```

7.Object Operations:  
Object methods can perform various operations on object data, such as manipulating properties, performing calculations, iterating over object properties, or interacting with other objects.  
  
Example:-  
  ```
const calculator =  
{  
	operand1: 0,  
	operand2: 0,  
	add()  
	{  
		return this.operand1 + this.operand2;  
	},  
	multiply()  
	{  
		return this.operand1 * this.operand2;  
	}  
};  
calculator.operand1 = 5;  
calculator.operand2 = 3;  
console.log(calculator.add());  
console.log(calculator.multiply());  
  
Output:  
8  
15  
  ```

These are the basic concepts of object methods and operations in JavaScript. Objects provide a powerful way to organize and work with related data and behavior in JavaScript.
  
## 7.Hoisting :
  
In JavaScript, hoisting is a mechanism where variable and function declarations are moved to the top of their containing scope during the compilation phase. This means that you can use variables and functions before they are declared in your code. However, it's important to note that only the declarations are hoisted, not the initializations or assignments.  
  
There are two types of hoisting in JavaScript: hoisting of variables and hoisting of functions.  
  
1.Hoisting of Variables:  
When variables are hoisted, the declaration of the variable is moved to the top of the scope, but the assignment or initialization remains in its original place. This means that you can use a variable before it is declared, but its value will be undefined until it is assigned a value.  
  
Example:  
```  
console.log(myVariable); // undefined  
var myVariable = 10;  
console.log(myVariable);  
  
Output :10  
  ```

The above code is actually interpreted as follows:  
  ```
var myVariable;  // Declaration is hoisted  
console.log(myVariable); // undefined  
myVariable = 10; // Assignment remains in its original place  
console.log(myVariable);  
Output : 10  
  ```

2.Hoisting of Functions:  
When functions are hoisted, both the function declaration and its body are moved to the top of the scope. This means that you can call a function before it is declared in your code.  
  
Example:  
  ```
myFunction();   
function myFunction()  
{  
	console.log("Hello, World!");  
}  
  ```

The above code is actually interpreted as follows:  
  ```
function myFunction()  
{ // Both declaration and body are hoisted  
		console.log("Hello, World!");  
}  
myFunction();  
  
output : "Hello, World!"  
  ```

It's important to be aware of hoisting in JavaScript to understand the behavior of your code. However, it's considered a best practice to declare variables and functions at the beginning of their scope to avoid any confusion or unexpected behavior.

## 8.Scopes :

In JavaScript, scopes determine the accessibility and visibility of variables, functions, and objects within your code. Understanding how scopes work is crucial for writing efficient and organized JavaScript programs. There are two main types of scopes in JavaScript: global scope and local scope (also known as function scope).  
  
1.Global Scope:  
- Variables declared outside of any function are considered to be in the global scope.  
- Global variables can be accessed from any part of your code, including inside functions.  
- When a variable is accessed, JavaScript first checks the local scope, and if the variable is not found, it looks in the global scope.  
- Global variables can be accessed and modified from any part of your code, which can lead to potential issues if not managed properly.  
  
Example of a global variable:  
```  
var globalVariable = 10;  
function myFunction()  
{  
	console.log(globalVariable);  // Accessing global variable  
}  
myFunction();  
  
Output: 10  
  ```

2.Local Scope (Function Scope):  
- Variables declared inside a function are considered to be in the local scope.  
- Local variables are accessible only within the function in which they are declared.  
- Each function has its own separate local scope, and variables with the same name can exist in different function scopes without conflict.  
- Local variables take precedence over global variables with the same name.  
  
Example of a local variable:  
  ```
function myFunction()  
{  
	var localVariable = 5; // Local variable  
	console.log(localVariable);  
}  
  
myFunction(); //Output: 5  
  
console.log(localVariable);  // Error: localVariable is not defined  
  ```

3.Block Scope (Introduced in ES6):  
- Starting from ECMAScript 2015 (ES6), JavaScript introduced block scope using the `let` and `const` keywords.  
- Variables declared with `let` and `const` inside a block (e.g., within loops or conditional statements) are limited to the block scope.  
- Block-scoped variables are not accessible outside the block in which they are defined.  
- Block scope helps prevent variable leakage and provides better control over variable lifespan.  
  
Example of block scope:  
```  
if (true)  
{  
	let blockScopedVariable = 20; // Block-scoped variable  
	console.log(blockScopedVariable);  
}  
console.log(blockScopedVariable); // Error: blockScopedVariable is not defined  
  ```

**Note: Prior to ES6, JavaScript had function scope but not block scope. Block-scoped variables introduced with `let` and `const` provide more granular control over variable scoping.**  
  
Understanding and utilizing scopes effectively is crucial for writing maintainable and bug-free JavaScript code.

## 9.Clousers :

It is a combination of a function and the lexical environment in which it was declared. It allows a function to access variables from its outer (enclosing) scope, even after the outer function has finished executing. In other words, a closure gives you access to an outer function's scope from an inner function.

Here's an example to illustrate closures:
```
function outerFunction() {
  const outerVariable = 'I am from outer';

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

  return innerFunction;
}

const inner = outerFunction();
inner(); // Prints: I am from outer
```

In the example above, `outerFunction` is the outer function that declares the `outerVariable`. The `innerFunction` is the inner function defined inside `outerFunction`. The `innerFunction` has access to the `outerVariable` even after `outerFunction` has finished executing. This is possible because of the closure.

The `outerVariable` is captured by the `innerFunction`, forming a closure. When `innerFunction` is invoked (`inner()`), it can still access and use the `outerVariable`.

Closures are commonly used to create private variables and encapsulation in JavaScript. By defining variables within an outer function and returning an inner function that can access and modify those variables, you can create a private scope where the variables are not directly accessible from the outside.
```
function createCounter() {
  let count = 0;

  return {
    increment() {
      count++;
    },
    decrement() {
      count--;
    },
    getCount() {
      return count;
    }
  };
}

const counter = createCounter();
console.log(counter.getCount()); // 0
counter.increment();
counter.increment();
console.log(counter.getCount()); // 2
counter.decrement();
console.log(counter.getCount()); // 1
```

In this example, the `createCounter` function returns an object with three methods: `increment`, `decrement`, and `getCount`. The `count` variable is enclosed within the scope of the `createCounter` function and can only be accessed or modified through the methods of the returned object. This creates a private variable that is protected from direct access or modification from outside the object.

Closures are powerful in JavaScript and provide a way to maintain state and create encapsulated functions with persistent access to their lexical environments. They are widely used in various JavaScript patterns and can be quite useful in functional programming, event handling, and asynchronous operations.