Hidden Gems: Lesser-Known Features in JavaScript
Tags: javascript, webdev, beginners, programming
Published: 2023-08-07 09:29:42

JavaScript is undoubtedly one of the most powerful and widely-used programming languages in the world. Most developers are familiar with the basic features, but there are a plethora of hidden gems that often go unnoticed. In this article, we will explore some of these rarely used functions and how they can make the development process more efficient and elegant.

## 1. `Object.getOwnPropertyDescriptors`

The `Object.getOwnPropertyDescriptors` function allows you to retrieve all property descriptors of an object. This can be particularly useful when you want to copy properties or clone objects without merely duplicating the values.

```javascript
const source = { name: 'Alice', age: 30 };
const descriptors = Object.getOwnPropertyDescriptors(source);

const target = Object.create(null);
for (const key in descriptors) {
  Object.defineProperty(target, key, descriptors[key]);
}

console.log(target); // { name: 'Alice', age: 30 }
```

## 2. `Array.from` with Mapping Function

The `Array.from` function is often used to create arrays from iterable objects. But did you know you can also pass a mapping function?

```javascript
const numbers = [1, 2, 3, 4];
const squared = Array.from(numbers, num => num * num);

console.log(squared); // [1, 4, 9, 16]
```

## 3. `String.prototype.trimStart` and `String.prototype.trimEnd`

Removing leading or trailing spaces from a string is a common task. With the `trimStart` and `trimEnd` functions, this becomes a breeze.

```javascript
const text = '   Hello, World!   ';
const trimmed = text.trimStart().trimEnd();

console.log(trimmed); // 'Hello, World!'
```

## 4. `Intl.Collator` for Natural String Sorting

The `Intl.Collator` function allows for correct natural sorting of strings in different languages and cultures.

```javascript
const words = ['äpfel', 'Zebra', 'Bär', 'Apfel', 'über'];
const collator = new Intl.Collator('de');

const sorted = words.sort(collator.compare);
console.log(sorted); // ['Apfel', 'äpfel', 'Bär', 'über', 'Zebra']
```

## 5. `Promise.allSettled`

While `Promise.all` aborts on an error, `Promise.allSettled` returns results for all passed promises, regardless of whether they were fulfilled or rejected.

```javascript
const promises = [
  Promise.resolve('Success'),
  Promise.reject('Error'),
  Promise.resolve('Another success')
];

Promise.allSettled(promises)
  .then(results => console.log(results))
  .catch(error => console.error(error));
```

Sure, Josun! Here's an addition about the `#` (private fields) operator in JavaScript classes, styled in Markdown:

---

## 6. Private Fields with the `#` Operator

One of the recent and significant additions to JavaScript is the introduction of private fields in classes using the `#` operator. This feature allows you to define properties that are truly private to the class instance, enhancing encapsulation and security.

Unlike traditional JavaScript properties, private fields cannot be accessed or modified from outside the class. This makes it easier to create robust and maintainable code.

### Defining and Using Private Fields

To define a private field, simply prefix the field name with `#`. You can then use this field within the class methods just like any other property.

```javascript
class Person {
  #name;
  #age;

  constructor(name, age) {
    this.#name = name;
    this.#age = age;
  }

  getDetails() {
    return `Name: ${this.#name}, Age: ${this.#age}`;
  }
}

const person = new Person('Alice', 30);
console.log(person.getDetails()); // Name: Alice, Age: 30

// Trying to access private fields from outside the class will result in an error
console.log(person.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class
```

### Benefits of Private Fields

1. **Encapsulation**: Private fields ensure that internal states of an object are hidden from the outside world. This helps in maintaining a clean and predictable interface.
2. **Security**: By restricting access to certain fields, you can prevent accidental or malicious modifications to an object's state.
3. **Code Clarity**: It is immediately clear which parts of the class are meant for internal use only, aiding in better understanding and maintenance of the code.

### Combining Private Fields with Public Methods

You can combine private fields with public methods to create well-defined interfaces for your classes.

```javascript
class BankAccount {
  #balance;

  constructor(initialBalance) {
    this.#balance = initialBalance;
  }

  deposit(amount) {
    if (amount > 0) {
      this.#balance += amount;
      return `Deposited ${amount}. New balance is ${this.#balance}.`;
    } else {
      return 'Invalid deposit amount';
    }
  }

  withdraw(amount) {
    if (amount > 0 && amount <= this.#balance) {
      this.#balance -= amount;
      return `Withdrew ${amount}. New balance is ${this.#balance}.`;
    } else {
      return 'Invalid withdrawal amount or insufficient funds';
    }
  }

  getBalance() {
    return `Current balance is ${this.#balance}`;
  }
}

const account = new BankAccount(100);
console.log(account.deposit(50)); // Deposited 50. New balance is 150.
console.log(account.withdraw(30)); // Withdrew 30. New balance is 120.
console.log(account.getBalance()); // Current balance is 120

// Direct access to the private field is not allowed
console.log(account.#balance); // SyntaxError: Private field '#balance' must be declared in an enclosing class
```


## Conclusion

These lesser-known JavaScript functions are like hidden treasures that can simplify your development tasks and make your code more elegant. By incorporating these functions into your projects, you can enhance your efficiency while making your code more readable and maintainable. Explore these features and use them wisely to unlock the full potential of JavaScript!