# Uncharted Territory: Exploring Lesser-Known JavaScript Functions

### **Using** `+` to Convert Strings to Numbers:

```javascript
const numericValue = +"42"; // Converts the string to a number
console.log(numericValue); // Output: 42 

const numericValue = +"abc";
console.log(numericValue); // Output: Nan
```

The `+` symbol is placed before the `stringNumber`, and it effectively coerces the string into a numeric value. It's important to note that if the string cannot be converted to a valid number, the result will be `NaN`

### **Double Bitwise NOT for Math.floor:**

```javascript
// Instead of
const rounded1 = Math.floor(4.9);
console.log(rounded1); // Output: 4
// Use
const rounded2 = ~~4.9;
console.log(rounded2); // Output: 4
```

### Swapping Values:

```javascript
// Use destructuring
let a = 5, b = 10;
[a, b] = [b, a];
```

Destructuring assignment can be used to exchange the values of two variables in a concise manner, as shown in the example: `[a, b] = [b, a];`. This eliminates the need for a temporary variable and simplifies the swapping process.

### Simplify Multiple Criteria Checks with Array.includes

**Without Array.includes:**

```javascript
const userRole = "admin";

// Check if the user role is one of the specified roles
if (userRole === "admin" || userRole === "editor" || userRole === "viewer") {
  console.log("User has a valid role!");
} else {
  console.log("Invalid user role.");
}
```

**With Array.includes:**

```javascript
const validRoles = ["admin", "editor", "viewer"];
const userRole = "admin";

// Check if the user role is in the array of valid roles
if (validRoles.includes(userRole)) {
  console.log("User has a valid role!");
} else {
  console.log("Invalid user role.");
}
```

## `Object.freeze` and Immutability:

```javascript
// Create a mutable object
const mutableObject = {
  property1: 'value1',
  property2: 'value2'
};
// Freeze the object to make it immutable
const immutableObject = Object.freeze(mutableObject);
// Attempt to modify a property - this will not throw an error, but it won't have any effect
immutableObject.property1 = 'new value';
// Attempt to add a new property - this will not throw an error, but it won't have any effect
immutableObject.property3 = 'value3';
// Attempt to delete a property - this will not throw an error, but it won't have any effect
delete immutableObject.property2;
// The original object remains unchanged
console.log(mutableObject); // { property1: 'new value', property2: 'value2' }
// The frozen object remains unchanged
console.log(immutableObject); // { property1: 'value1', property2: 'value2' }
```

`Object.freeze` makes an object immutable, preventing changes to its properties.

Although `Object.freeze` is handy for preventing changes to an object's properties, it's important to keep in mind that it doesn't ensure deep immutability. If your object has nested objects, those nested parts might still be mutable. If you need full deep immutability, you might want to consider taking extra steps or using libraries like [**Immutable.js**](https://immutable-js.com/), which specifically support immutable data structures.

### **Logical AND for Short-Circuit Evaluation:**

```javascript
// Instead of if-else
let result;
if (condition) {
  result = 'True';
} else {
  result = 'False';
}

// Use logical AND
let result = condition && 'True' || 'False';
```

### Early Returns & Less Nesting

#### **Less Desirable Example:**

```javascript
function calculatePrice(quantity, price) {
  if (quantity > 0) {
    if (price > 0) {
      let totalPrice = quantity * price;

      if (quantity >= 10) {
        totalPrice *= 0.9; // 10% discount for quantities of 10 or more
      }

      return totalPrice;
    } else {
      console.error("Invalid input: Price must be a positive value.");
    }
  } else {
    console.error("Invalid input: Quantity must be a positive value.");
  }
}
const finalPrice = calculatePrice(15, 5);
```

#### **Good Example:**

```javascript
function calculatePrice(quantity, price) {
  // Validate input parameters
  if (quantity <= 0 || price <= 0) {
    console.error("Invalid input: Quantity and price must be positive values.");
    return;
  }

  // Calculate total price
  const totalPrice = quantity * price;

  // Apply discount for bulk purchases
  if (quantity >= 10) {
    return totalPrice * 0.9; // 10% discount for quantities of 10 or more
  }

  return totalPrice;
}
const finalPrice = calculatePrice(15, 5);
```

The "Less Nesting, Return Early" coding style provides benefits such as improved readability, better error handling, and easier debugging. It simplifies code structure and makes it more straightforward to understand and maintain.

### **Nullish Coalescing Operator (**`??`):

```javascript
// Instead of logical OR
const value = (someVariable !== null && someVariable !== undefined) ? someVariable : 'default';
// Use nullish coalescing operator
const value = someVariable ?? 'default';
```

The Nullish Coalescing Operator (`??`) efficiently provides default values for variables, ensuring the right-hand operand is used only when the left-hand operand is `null` or `undefined`.

### Often underutilized Array methods in JavaScript:

1. **<mark>flat</mark>** and **<mark>flatMap</mark>**:
    
    * `flat`: Flattens nested arrays.
        
    * `flatMap`: Maps each element using a mapping function and then flattens the result.
        
    
    ```javascript
    let nestedArray = [1, [2, [3]]];
    let flatArray = nestedArray.flat(); // [1, 2, [3]]
    let mappedFlatArray = nestedArray.flatMap(value => [value * 2]); // [2, 4, 6]
    ```
    
2. **<mark>from</mark>** with a Mapping Function:
    
    * Creates a new array with the results of calling a provided function on every element in the array.
        
    
    ```javascript
    let array = [1, 2, 3];
    let squaredArray = Array.from(array, x => x * x); // [1, 4, 9]
    ```
    
3. **<mark>Reverses</mark>** the elements of an array in place.
    
    ```javascript
    let array = [1, 2, 3, 4, 5];
    array.reverse(); // [5, 4, 3, 2, 1]
    ```
    
4. **<mark>Array.some: </mark>** Checks if at least one element in the array satisfies a provided condition.
    
    ```javascript
    let hasPositiveNumber = [-1, 0, 1, 2].some(num => num > 0); // true
    ```
    
5. **<mark>Array.every</mark>:** Checks if all elements in the array satisfy a provided condition.
    
    ```javascript
    let allPositiveNumbers = [1, 2, 3, 4].every(num => num > 0); // true
    ```
    
6. **<mark>Array.reduceRight</mark>:** Applies a function against an accumulator and each element in the array (from right to left) to reduce it to a single value.
    
    ```javascript
    let reversedString = ['a', 'b', 'c'].reduceRight((acc, char) => acc + char, ''); // 'cba'
    ```
    

### Lesser-known examples of using `toLocaleString` for various scenarios:

1. **Basic Number Formatting:**
    
    ```javascript
    let number = 1234567.89;
    let formattedNumber = number.toLocaleString(); // "1,234,567.89"
    ```
    
2. **Currency Formatting:**
    
    ```javascript
    let price = 12345.67;
    let formattedPrice = price.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); // "$12,345.67"
    ```
    
3. **Date Formatting:**
    
    ```javascript
    let date = new Date('2023-01-01T12:34:56');
    let formattedDate = date.toLocaleString('en-US', { dateStyle: 'full', timeStyle: 'short' });
    // "Sunday, January 1, 2023 at 12:34 PM"
    ```
    
4. **Percentage Formatting:**
    
    ```javascript
    let percentage = 0.456;
    let formattedPercentage = percentage.toLocaleString('en-US', { style: 'percent' }); // "45.6%"
    ```
    
5. **Grouping Options:**
    
    ```javascript
    let largeNumber = 9876543210;
    let formattedLargeNumber = largeNumber.toLocaleString('en-US', { useGrouping: false }); // "9876543210"
    ```
    
6. **Compact Display for Large Numbers:**
    
    ```javascript
    let largeNumber = 12345678901234567890;
    let formattedLargeNumber = largeNumber.toLocaleString('en-US', { notation: 'compact' }); // "12.3Q"
    ```
    
7. **Customizing Decimal and Thousand Separators:**
    
    ```javascript
    let customFormattedNumber = 9876543.21.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 4 });
    // "9,876,543.2100"
    ```
    
8. **Using Locales for Different Regions:**
    
    ```javascript
    let number = 12345.67;
    let formattedNumberFrench = number.toLocaleString('fr-FR'); // "12 345,67"
    let formattedNumberGerman = number.toLocaleString('de-DE'); // "12.345,67"
    ```
