Read post in original url 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
- The Right Way to Clone Nested Object/Array (Deep Clone) 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:
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:
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:
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:
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:
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:
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:
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
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:
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:
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.
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.
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.
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
// 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:
// 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!
Top comments (11)
There is no such operator, you are merely using the logical not operator (
!
) twice. Describing it as a single operator merely serves to create misunderstanding as to what is actually going on.Officially, if we only refer to MDN docs, you are right. Its not a new operator. Its just a double NOT operator. But not everyone knows that we can do this, hence i include it here π
Regarding the name "Bang", as @webjose refer to western movies, here is the truth:
en.wikipedia.org/wiki/Exclamation_...
Thank you for the trivia π
At least rename it to "double negation operators". Bang Bang?? Are we in a western movie? That's messed up. LOL.
If you search in google using that keyword, many people actually call it that way.. i didnt invent that word π
But hey, lets focus on its function instead of how we should call it, shall we? π
This list is great. Thanks @syakirurahman
You're welcome. hope it helps! π
Thank you, I learned some things to start utilizing more π
No problem.. Tell me what you learn from here? π