20 Lesser-known Javascript Features that You Probably Never Used
Tags: webdev, javascript, beginners, tutorial
Published: 2024-07-11 15:11:15

**Read post in original url [https://devaradise.com/lesser-known-javascript-features](https://devaradise.com/lesser-known-javascript-features/) for better navigation**

JavaScript is a cornerstone of modern web development, powering dynamic websites and applications. While many developers familiar with the basic and widely used features of JavaScript, numerous hidden features often go unnoticed. These lesser-known features can make your code more concise, readable, and powerful.

In this article, we'll explore some hidden JavaScript features. From the nullish coalescing operator to Map and Set objects, each feature includes practical examples and best practices. Utilizing these features can help you write cleaner, more efficient code and tackle complex problems easily.

Whether you're a seasoned developer or a beginner, this article will introduce you to underutilized JavaScript capabilities. By the end, you'll have new techniques to elevate your coding skills with Javascript.

#### Other posts about Javascript

- [JavaScript Array/Object Destructuring Explained + Examples](/js-array-object-destructuring/)
- [The Right Way to Clone Nested Object/Array (Deep Clone) in Javascript](/deep-clone-nested-object-array-in-javascript/)

## Lesser-known Javascript Features

### 1. Nullish Coalescing Operator

The nullish coalescing operator (`??`) is used to provide a default value when a variable is `null` or `undefined`.

#### Code Example:

```javascript
let foo = null;
let bar = foo ?? 'default value';
console.log(bar); // Output: 'default value'
```

Use the nullish coalescing operator to handle cases where `null` or `undefined` values may appear, ensuring that your code runs smoothly with default values.

### 2. Optional Chaining

The optional chaining operator (`?.`) allows safe access to deeply nested object properties, avoiding runtime errors if a property does not exist.

#### Code Example:

```javascript
const user = {
	profile: {
		name: 'Alice'
	}
};
const userProfileName = user.profile?.name;
console.log(userProfileName); // Output: 'Alice'

const userAccountName = user.account?.name;
console.log(userAccountName); // Output: undefined
```

Use optional chaining to avoid errors when accessing properties of potentially `null` or `undefined` objects, making your code more robust.

### 3. Numeric Separators

Numeric separators (`_`) make large numbers more readable by visually separating digits.

#### Code Example:

```javascript
const largeNumber = 1_000_000;
console.log(largeNumber); // Output: 1000000
```

Use numeric separators to improve the readability of large numbers in your code, especially for financial calculations or large datasets.

### 4. Promise.AllSettled

`Promise.allSettled` waits for all promises to settle (either fulfilled or rejected) and returns an array of objects describing the outcome.

#### Code Example:

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

Promise.allSettled(promises).then((results) => {
	results.forEach((result) => console.log(result));
});
// Output:
// { status: 'fulfilled', value: 'Success' }
// { status: 'rejected', reason: 'Error' }
// { status: 'fulfilled', value: 'Another Success' }
```

Use `Promise.allSettled` when you need to handle multiple promises and want to ensure that all results are processed, regardless of individual promise outcomes.

### 5. Private Class Fields

Private class fields are properties that can only be accessed and modified within the class they are declared.

#### Code Example:

```javascript
class MyClass {
	#privateField = 42;

	getPrivateField() {
		return this.#privateField;
	}
}

const instance = new MyClass();
console.log(instance.getPrivateField()); // Output: 42
console.log(instance.#privateField); // Uncaught Private name #privateField is not defined.
```

Use private class fields to encapsulate data within a class, ensuring that sensitive data is not exposed or modified outside the class.

### 6. Logical Assignment Operators

Logical assignment operators (`&&=`, `||=`, `??=`) combine logical operators with assignment, providing a concise way to update variables based on a condition.

#### Code Example:

```javascript
let a = true;
let b = false;

a &&= 'Assigned if true';
b ||= 'Assigned if false';

console.log(a); // Output: 'Assigned if true'
console.log(b); // Output: 'Assigned if false'
```

Use logical assignment operators to simplify conditional assignments, making your code more readable and concise.

### 7. Labels for Loop and Block Statements

Labels are identifiers followed by a colon, used to label loops or blocks for reference in break or continue statements.

#### Code Example:

```javascript
outerLoop: for (let i = 0; i < 3; i++) {
	console.log(`Outer loop iteration ${i}`);
	for (let j = 0; j < 3; j++) {
		if (j === 1) {
			break outerLoop; // Break out of the outer loop
		}
		console.log(`  Inner loop iteration ${j}`);
	}
}
// Output:
// Outer loop iteration 0
//   Inner loop iteration 0
```

```javascript
labelBlock: {
	console.log('This will be printed');
	if (true) {
		break labelBlock; // Exit the block
	}
	console.log('This will not be printed');
}
// Output:
// This will be printed
```

Use labels to control complex loop behavior, making it easier to manage nested loops and improve code clarity.

### 8. Tagged Template Literals

Tagged template literals allow you to parse template literals with a function, enabling custom processing of string literals.

#### Code Example 1:

```javascript
function logWithTimestamp(strings, ...values) {
	const timestamp = new Date().toISOString();
	return (
		`[${timestamp}] ` +
		strings.reduce((result, str, i) => {
			return result + str + (values[i] || '');
		})
	);
}

const user = 'JohnDoe';
const action = 'logged in';
console.log(logWithTimestamp`User ${user} has ${action}.`);
// Outputs: [2024-07-10T12:34:56.789Z] User JohnDoe has logged in.
```

#### Code Example 2:

```javascript
function validate(strings, ...values) {
	values.forEach((value, index) => {
		if (typeof value !== 'string') {
			throw new Error(`Invalid input at position ${index + 1}: Expected a string`);
		}
	});
	return strings.reduce((result, str, i) => {
		return result + str + (values[i] || '');
	});
}

try {
	const validString = validate`Name: ${'Alice'}, Age: ${25}`;
	console.log(validString); // This will throw an error
} catch (error) {
	console.error(error.message); // Outputs: Invalid input at position 2: Expected a string
}
```

Use tagged template literals for advanced string processing, such as creating safe HTML templates or localizing strings.

### 9. Bitwise Operators for Quick Math

Bitwise operators in JavaScript perform operations on binary representations of numbers. They are often used for low-level programming tasks, but they can also be handy for quick mathematical operations.

#### List of Bitwise Operators

- `&` (AND)
- `|` (OR)
- `^` (XOR)
- `~` (NOT)
- `<<` (Left shift)
- `>>` (Right shift)
- `>>>` (Unsigned right shift)

#### Code Example 1:

You can use the AND operator to check if a number is even or odd.

```javascript
const isEven = (num) => (num & 1) === 0;
const isOdd = (num) => (num & 1) === 1;

console.log(isEven(4)); // Outputs: true
console.log(isOdd(5)); // Outputs: true
```

#### Code Example 2:

You can use left shift (<<) and right shift (>>) operators to multiply and divide by powers of 2, respectively.

```javascript
const multiplyByTwo = (num) => num << 1;
const divideByTwo = (num) => num >> 1;

console.log(multiplyByTwo(5)); // Outputs: 10
console.log(divideByTwo(10)); // Outputs: 5
```

#### Code Example 3:

You can check if a number is a power of 2 using the AND operator.

```javascript
const isPowerOfTwo = (num) => num > 0 && (num & (num - 1)) === 0;

console.log(isPowerOfTwo(16)); // Outputs: true
console.log(isPowerOfTwo(18)); // Outputs: false
```

Use bitwise operators for performance-critical applications where low-level binary manipulation is required, or for quick math operations.

### 10. `in` Operator for Property Checking

The `in` operator checks if a property exists in an object.

#### Code Example:

```javascript
const obj = { name: 'Alice', age: 25 };
console.log('name' in obj); // Output: true
console.log('height' in obj); // Output: false
```

Use the `in` operator to verify the existence of properties in objects, ensuring that your code handles objects with missing properties gracefully.

### 11. `debugger` Statement

The `debugger` statement invokes any available debugging functionality, such as setting a breakpoint in the code.

#### Code Example:

```javascript
function checkValue(value) {
	debugger; // Execution will pause here if a debugger is available
	return value > 10;
}
checkValue(15);
```

Use the `debugger` statement during development to pause execution and inspect code behavior, helping you identify and fix bugs more efficiently.

### 12. Chained Assignment

Chained assignment allows you to assign a single value to multiple variables in a single statement.

#### Code Example:

```javascript
let a, b, c;
a = b = c = 10;
console.log(a, b, c); // Output: 10 10 10
```

Use chained assignment for initializing multiple variables with the same value, reducing code redundancy.

### 13. Dynamic Function Names

Dynamic function names allow you to define functions with names computed at runtime.

#### Code Example:

```javascript
const funcName = 'dynamicFunction';
const obj = {
	[funcName]() {
		return 'This is a dynamic function';
	}
};

console.log(obj.dynamicFunction()); // Output: 'This is a dynamic function'
```

Use dynamic function names to create functions with names based on runtime data, enhancing code flexibility and reusability.

### 14. Get Function Arguments

The `arguments` object is an array-like object that contains the arguments passed to a function.

#### Code Example:

```javascript
function sum() {
	let total = 0;
	for (let i = 0; i < arguments.length; i++) {
		total += arguments[i];
	}
	return total;
}

console.log(sum(1, 2, 3)); // Outputs: 6
```

Use the `arguments` object to access all arguments passed to a function, useful for functions with variable-length arguments.

### 15. Unary `+` Operator

The unary operator (`+`) converts its operand into a number.

#### Code Example:

```javascript
console.log(+'abc'); // Outputs: NaN
console.log(+'123'); // Outputs: 123
console.log(+'45.67'); // Outputs: 45.67 (converted to a number)

console.log(+true); // Outputs: 1
console.log(+false); // Outputs: 0

console.log(+null); // Outputs: 0
console.log(+undefined); // Outputs: NaN
```

Use the unary operator for quick type conversion, especially when working with user input or data from external sources.

### 16. Exponentiation `**` Operator

The exponentiation operator (`**`) performs exponentiation (power) of its operands.

#### Code Example:

```javascript
const base = 2;
const exponent = 3;
const result = base ** exponent;
console.log(result); // Output: 8
```

Use the exponentiation operator for concise and readable mathematical expressions involving powers, such as in scientific or financial calculations.

### 17. Function Properties

Functions in JavaScript are objects and can have properties.

#### Code Example 1:

```javascript
function myFunction() {}
myFunction.description = 'This is a function with a property';
console.log(myFunction.description); // Output: 'This is a function with a property'
```

#### Code Example 2:

```javascript
function trackCount() {
	if (!trackCount.count) {
		trackCount.count = 0;
	}
	trackCount.count++;
	console.log(`Function called ${trackCount.count} times.`);
}
trackCount(); // Outputs: Function called 1 times.
trackCount(); // Outputs: Function called 2 times.
trackCount(); // Outputs: Function called 3 times.
```

Use function properties to store metadata or configuration related to the function, enhancing the flexibility and organization of your code.

### 18. Object Getters & Setters

Getters and setters are methods that get or set the value of an object property.

#### Code Example:

```javascript
const obj = {
	firstName: 'John',
	lastName: 'Doe',
	_age: 0, // Conventionally use an underscore for the backing property
	get fullName() {
		return `${this.firstName} ${this.lastName}`;
	},
	set age(newAge) {
		if (newAge >= 0 && newAge <= 120) {
			this._age = newAge;
		} else {
			console.log('Invalid age assignment');
		}
	},
	get age() {
		return this._age;
	}
};

console.log(obj.fullName); // Outputs: 'John Doe'
obj.age = 30; // Setting the age using the setter
console.log(obj.age); // Outputs: 30

obj.age = 150; // Attempting to set an invalid age
// Outputs: 'Invalid age assignment'
console.log(obj.age); // Still Outputs: 30 (previous valid value remains)
```

Use getters and setters to encapsulate the internal state of an object, providing a controlled way to access and modify properties.

### 19. `!!` Bang Bang Operator

The `!!` (double negation) operator converts a value to its boolean equivalent.

#### Code Example:

```javascript
const value = 'abc';
const value1 = 42;
const value2 = '';
const value3 = null;
const value4 = undefined;
const value5 = 0;

console.log(!!value); // Outputs: true (truthy value)
console.log(!!value1); // Outputs: true (truthy value)
console.log(!!value2); // Outputs: false (falsy value)
console.log(!!value3); // Outputs: false (falsy value)
console.log(!!value4); // Outputs: false (falsy value)
console.log(!!value5); // Outputs: false (falsy value)
```

Use the `!!` operator to quickly convert values to booleans, useful in conditional expressions.

### 20. Map and Set Objects

`Map` and `Set` are collections with unique features. `Map` holds key-value pairs, and `Set` holds unique values.

#### Code Example 1:

```javascript
// Creating a Map
const myMap = new Map();

// Setting key-value pairs
myMap.set('key1', 'value1');
myMap.set(1, 'value2');
myMap.set({}, 'value3');

// Getting values from a Map
console.log(myMap.get('key1')); // Outputs: 'value1'
console.log(myMap.get(1)); // Outputs: 'value2'
console.log(myMap.get({})); // Outputs: undefined (different object reference)
```

#### Code Example 2:

```javascript
// Creating a Set
const mySet = new Set();

// Adding values to a Set
mySet.add('apple');
mySet.add('banana');
mySet.add('apple'); // Duplicate value, ignored in a Set

// Checking size and values
console.log(mySet.size); // Outputs: 2 (only unique values)
console.log(mySet.has('banana')); // Outputs: true

// Iterating over a Set
mySet.forEach((value) => {
	console.log(value);
});
// Outputs:
// 'apple'
// 'banana'
```

Use `Map` for collections of key-value pairs with any data type as keys, and `Set` for collections of unique values, providing efficient ways to manage data.

## Conclusion

By leveraging these lesser-known JavaScript features, you can write more efficient, readable, and robust code. Start integrating these techniques into your projects to take your JavaScript skills to the next level.

We hope this guide has provided you with valuable insights and practical examples to help you leverage these hidden JavaScript features. Don't hesitate to experiment with them and see how they can fit into your coding practices.

If you found this article helpful, please share it with your fellow developers and friends. I'd love to hear your thoughts and experiences with these features, so feel free to leave a comment below.

Thanks. Happy coding!