Hidden Gems in Modern JavaScript You Should Be Using
Professional Services, Technical Blog
JavaScript has evolved dramatically in recent years, with big updates and features such as ES6 classes and async/await. It has also introduced powerful new operators and methods that often fly under the radar. These “hidden gems” include new operators such as the nullish coalescing and optional chaining operators for null checking and the spread, rest, and logical assignment operators for simplifying working with objects and arrays.
Optional Chaining
The optional chaining operator ( ?. ) helps to avoid the dreaded “cannot read property of undefined” error by providing access to deeply nested object properties without causing an error to be thrown if a property in the chain is undefined or null.
const user = { profile: { name: "Alice" } }; console.log(user?.profile?.name); // Output: "Alice" console.log(user?.settings?.theme); // Output: undefined
It also works when using dynamic property names (ex: settings.theme?.[“propertyName”] ). This operator is particularly useful when working with optional or unpredictable data and can even call methods safely. For example, if the method “greet” doesn’t exist, user.greet?.() won’t throw an error. While it is powerful, optional chaining can be overused, as it can mask potential issues in code. Debugging may become harder if things are silently bypassed; therefore, it is best used for truly optional or unpredictable data.
Nullish Coalescing and Logical Assignment
The nullish coalescing operator ( ?? ) is similar to the logical OR operator in that both can provide a default value if the first one is missing. Whereas the OR operator uses the right-hand value if the left is falsy, the nullish coalescing operator uses the right-hand value if the left is null or undefined:
const userInput = null; const defaultValue = "Default Value"; console.log(userInput ?? defaultValue); // Output: "Default Value"
While often either could be used, the OR operator can be problematic when the left-hand value can contain “” or 0, as they are falsy values.
Logical assignment operators (e.g., ||= , &&= , and ??= ) simplify conditional assignments, reducing the need for verbose if-else statements. The logical OR assignment ( ||= ) assigns the right-hand operand to the left-hand operand if the left-hand operand is falsy.
let config = {}; config.theme ||= "dark"; // Assign if falsy console.log(config.theme); // Output: "dark"
Similarly, the logical AND assignment ( &&= ) assigns the right-hand operand to the left-hand operand if the left-hand operand is truthy, and the nullish coalescing assignment does the same if the left-hand operand is null or undefined. By using these operators, developers can make their code more concise to improve readability and reduce the amount of boilerplate code.
let config = { theme: "dark" }; config.theme &&= "light"; // Assign if truthy console.log(config.theme); // Output: "light" let config; config ??= { theme: "dark" }; // Assign if null or undefined console.log(config.theme); // Output: "dark"
Spread and Rest
The spread and rest operators use the same syntax ( … ) but serve different purposes. The spread operator is useful for combining arrays and merging objects:
const numbers1 = [1, 2, 3]; const numbers2 = [4, 5, 6]; const combinedNumbers = [...numbers1, ...numbers2]; // [1, 2, 3, 4, 5, 6] const obj1 = { a: 1, b: 2 }; const obj2 = { c: 3, d: 4 }; const mergedObject = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
While older methods like concat, push, and apply still exist for arrays, the spread operator avoids the verbosity of those methods and makes code cleaner and more readable. It is also immutable, which helps ensure data integrity, as well as more versatile, as it can be combined with other operations such as adding individual elements during the merge.
The spread operator can also be used to create shallow copies of arrays and objects:
const originalArray = [1, 2, 3]; const copiedArray = [...originalArray]; // [1, 2, 3] const originalObject = { a: 1, b: 2 }; const copiedObject = { ...originalObject }; // { a: 1, b: 2 }
Similar to combining arrays and objects, older methods such as slice, concat, and Object.assign exist; however, the spread operator again helps to avoid the verbosity of those methods.
The rest operator collects multiple function arguments into a single array. This allows the creation of functions that accept an indefinite number of arguments. This one must be the last in the function definition if included with other explicit parameters.
function sum(...numbers) { let total = 0; for (const number of numbers) { total += number; } return total; } const result1 = sum(1, 2, 3); // 6 const result2 = sum(4, 5, 6, 7, 8); // 30
These operators help highlight the continuing evolution of JavaScript and the tools it provides for writing more efficient, readable, and maintainable code. These hidden gems might not grab headlines, but they are small and easy-to-use tools that can be quickly incorporated into today’s application development and will help transform how you write and maintain your code.
Stay tuned for next month’s blog, where we’ll explore other hidden gems outside of operators, including new array functions and the dynamic import feature.

Jeremy Walker
Jeremy Walker is a Senior Software Engineer at INSPYR Solutions with over 13 years of experience. He specializes in building websites and mobile apps using JavaScript. A tech enthusiast at heart, he also enjoys movies, gaming, and exploring the outdoors in his free time. For inquiries, you can reach him at jwalker@inspyrsolutions.com.
Share This Article
Contact Us
We’re here for you when you need us. How can we help you today?