Join our community of software engineering leaders and aspirational developers. Always
stay in-the-know by getting the most important news and exclusive content delivered
fresh to your inbox to learn more about at-scale software development.
REQUIRED
It seems that you've previously unsubscribed from our newsletter
in the past. Click the button below to open the re-subscribe form
in a new tab. When you're done, simply close that tab and continue
with this form to complete your subscription.
The New Stack does not sell your information or share it with
unaffiliated third parties. By continuing, you agree to our
Terms of Use and
Privacy Policy.
Welcome and thank you for joining The New Stack community!
Please answer a few simple questions to help us deliver the news and resources you are interested in.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Great to meet you!
Tell us a bit about your job so we can cover the topics you find most relevant.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Welcome!
We’re so glad you’re here. You can expect all the best TNS content to arrive
Monday through Friday to keep you on top of the news and at the top of your game.
What’s next?
Check your inbox for a confirmation email where you can adjust your preferences
and even join additional groups.
Follow TNS on your favorite social media networks.
JavaScript isn’t just a language — it’s a specialized craft. And like any skilled martial art, the difference between being a novice and a master lies in the techniques you perfect. Anyone can write code that works, but writing code that’s clean, powerful and elegantly expressive is where true JavaScript Kung Fu begins.
Let’s deep dive into elevated JavaScript techniques that will make your code stand out from the crowd. It doesn’t matter if you’re building enterprise software or just sharpening your skills, these patterns will help you write cleaner, faster and more maintainable code — the kind that will make your future self (and teammates) nod with respect.
We’ll cover everything from:
Smart console.log practices that go beyond the basics
Using ES6 features like template literals, destructuring and spread operators for clearer, more intuitive logic
Writing more expressive conditionals with short-circuit evaluation
Using tools like `console.table()` and `console.time()` for debugging and performance profiling
And combining arrays like a boss, even with duplicates
Think of this as your dojo for modern JavaScript mastery. You’ve got the basics, but you’re ready to take it up a level.
Let’s code like a sensei.
1. Console.log Techniques: Logging Like a Pro
In the early stages of JavaScript development, many developers rely heavily on basic `console.log()` statements. While it gets the job done, advanced developers know there are far more powerful and cleaner ways to log data, especially when working with structured objects, debugging or profiling performance. Consider this simple example:
While this works, it’s harder to distinguish between the logs, especially when dealing with multiple variables. Now, let’s explore cleaner alternatives.
2. Computed Property Logging
Instead of logging variables one by one, you can use shorthand object property names to group your logs into a single object, making them more readable:
This is especially useful in large applications where you need to visually separate logs from one another, such as highlighting warnings, steps or critical state updates.
4. Displaying Objects in a Table With `console.table()`
When dealing with arrays of objects (or even a single object with multiple similar keys), `console.table()` is a visually superior alternative:
console.table([student, tutor]);
This logs a structured table with rows and columns, making it easy to scan and compare values. It’s ideal when you’re working with datasets like API responses, lists of users or status objects.
5. Benchmarking With `console.time()` and `console.timeEnd()`
Performance profiling is critical in JavaScript, especially when loops or operations may impact responsiveness. Use `console.time()` and `console.timeEnd()` to measure execution time:
console.time('loop');
let i = 0;
while (i < 1000000) {
i++;
}
console.timeEnd('loop');
//This will print something like
loop: 5.384ms
This gives you insight into how long your logic takes to execute, helping with optimization decisions or detecting bottlenecks in your code.
By mastering these enhanced logging techniques, you’re not just printing data — you’re communicating intent, improving readability and debugging smarter. These tools are part of your JavaScript utility belt, helping you become more efficient, organized and effective in your development workflow.
Template Literals: Writing Strings With Superpowers
Gone are the days of messy string concatenation using the + operator. With template literals, introduced in ES6, JavaScript gives you a cleaner, more expressive way to build strings, especially when variables and expressions are involved. Template literals are enclosed in backticks instead of single or double quotes, and they support interpolation, multiline strings and even embedded expressions.
Let’s break it down:
//Basic String Interpolation
const name = 'Ray';
const age = 20;
console.log(`My name is ${name} and I am ${age} years old.`);
Instead of writing:
'My name is ' + name + ' and I am ' + age + ' years old.'
Template literals let you inject variables directly into your string using `${}`. This not only reduces clutter but also boosts readability and maintainability.
// Multiline Strings (No \n Needed!)
const message = `Hello,
This is a multiline message,
Neatly written with template literals.`;
console.log(message);
Previously, you’d have to use `\n` or concatenate lines awkwardly. With backticks, you just write across lines naturally.
//Expressions and Function Calls Inside Template Literals
const price = 100;
const discount = 0.2;
console.log(`Final price after discount: ${price - (price * discount)} UGX`);
You can even call functions inside:
function greet(name) {
return `Hello, ${name.toUpperCase()}!`;
}
console.log(`${greet('ray')}`);
Template literals make your code more expressive and cleaner, especially in scenarios involving dynamic data, API responses or logging. Whether you’re crafting UI messages, generating reports or debugging output, this feature adds elegance and power to your strings.
Using `reduce()` To Get Totals: From Clunky Loops To Clean Logic
When working with arrays of numbers or objects, it’s common to calculate a total, be it prices, scores or item quantities. Many developers fall into the trap of using verbose `forloops` or `forEach()` to accomplish this. While those methods work, they’re often less expressive and harder to maintain. The `reduce()` method offers a powerful and elegant alternative that not only condenses your code but also enhances its readability and intent.
// Bad Code – Using forEach() for Totals
const cart = [
{ item: 'Book', price: 15 },
{ item: 'Pen', price: 5 },
{ item: 'Notebook', price: 10 },
];
let total = 0;
cart.forEach(product => {
total += product.price;
});
console.log(`Total price: ${total} UGX`);
This approach works, but it’s verbose, especially in large codebases. You’re manually managing the total, which can lead to errors and side effects.
`acc` (accumulator) starts at `0` (the second argument of `reduce()`).
On each iteration, it adds `curr.price` to `acc`.
After the loop finishes, you get the final total — clean, functional and declarative.
You can even make it more expressive with arrow functions and default values:
const total = cart.reduce((sum, { price }) => sum + price, 0);
This version uses destructuring to directly access the price of each item, making the code more readable.
So next time you’re summing values in an array, ditch the loop and reach for `reduce()`. It’s the functional way to write logic that’s not just correct, but clean and powerful.
Understanding the Spread Operator and Array Merging
The spread operator (…) is one of the most elegant and versatile features introduced in ES6. It allows you to “spread” the elements of an iterable (like arrays or objects) into individual elements. This comes in handy especially when merging arrays, cloning or passing multiple values in a function call.
The new method is much cleaner, more expressive and easier to understand. You’re literally just saying: “Spread the values of arr1 and arr2 into one new array.”
In case of duplicates, merge with Set and the spread operator.
Let’s assume the arrays have duplicate values:
We now have duplicate values. In many cases (like IDs, tags, etc.), we want unique values.
So to remove the duplicate values, we can use Set and the spread operator.
To give you context, `Set` is a built-in object that only stores unique values. We first use […] to merge the arrays. We then wrap it with `new Set(…)` to filter out duplicates, and finally, we spread that back into a new array.
Cloning an Array With Spread
If you ever want to copy an array without modifying the original, use the spread operator:
The rest operator (…) looks exactly like the spread operator, but it works in the opposite way. While the spread operator expands items, the rest operator gathers items into a single array or object.
It’s used mainly in:
Function arguments
Array destructuring
Object destructuring
1. Rest in Function Parameters
Sometimes, you don’t know how many arguments a function will receive. Instead of listing them manually, use the rest operator to bundle them up.
Explanation:
We pull out the name property.
The rest operator collects the remaining key-value pairs into `rest`.
While the rest (…) and spread (…) operators look identical in syntax, their behavior and purpose are fundamentally different. The spread operator is used to expand an array or object into individual elements or properties. You’ll typically see it used when passing arguments into a function or when combining arrays and objects. In contrast, the rest operator does the opposite. It’s used to gather multiple values into a single array or object. It’s commonly applied in function parameters to accept an indefinite number of arguments or in destructuring to collect remaining values. Think of it this way: Spread expands outward, breaking structures apart, while rest gathers inward, bundling them together. This subtle yet powerful distinction is key to writing flexible and clean JavaScript code.
Understanding Object Data Extraction in JavaScript
In JavaScript, object destructuring is a shorthand syntax that allows you to pull out properties from objects (or elements from arrays) into standalone variables. This makes your code cleaner and reduces redundancy.
Let’s take a basic object:
While this works just fine, it can become verbose or repetitive, especially when you need to reference the same property multiple times.
Now Let’s Use Destructuring for Cleaner Code
Instead of repeatedly writing `me.age`, you can destructure like this:
Notice how we used an alias. We didn’t extract the `likes` array itself, but instead unpacked its elements directly into `first` and `second`.
Nullish Coalescing (??)
The nullish coalescing operator (??) is used to provide a default value when a variable is `null` or `undefined`. It’s especially useful when you want to fall back only for truly “empty” values and not for falsy values like `0`, `”` or `false`.
Without nullish coalescing:
const age = 0;
const result = age || 18;
console.log(result); // 18 ❌ (0 is falsy, so it falls back)
With nullish coalescing:
const age = 0;
const result = age ?? 18;
console.log(result); // 0 ✅
Explanation:
|| falls back for any falsy value (`0`, `false`, `”`, `null`, `undefined`).
?? falls back only for `null` or `undefined`.
Converting Strings to Integers Using the + Sign
In JavaScript, the unary plus (+) operator can be used to quickly convert strings into numbers.
Traditional method:
This is a quick and readable trick when you’re sure the string contains a valid number. If it doesn’t, the result will be `NaN`.
See the code below:
console.log(+'hello'); // NaN
Optional Chaining (?.)
Optional chaining lets you safely access deeply nested object properties without having to check if each level exists. If the reference is `null` or `undefined`, it returns `undefined` instead of throwing an error.
Without optional chaining:
const user = {};
console.log(user.profile.name); // ❌ Error: Cannot read property 'name' of undefined
With optional chaining:
const user = {};
console.log(user.profile?.name); // ✅ undefined
You can also use it with functions:
user.sayHi?.(); // Only calls sayHi if it exists
This is great for handling data from APIs** where some fields may be missing.
The Ternary Operator
The ternary operator is a shorthand for `if/else`. It follows this syntax:
condition ? valueIfTrue : valueIfFalse;
To give you context, see the code below:
const age = 20;
const canVote = age >= 18 ? 'Yes' : 'No';
console.log(canVote); // "Yes"
This is equivalent to:
let canVote;
if (age >= 18) {
canVote = 'Yes';
} else {
canVote = 'No';
}
}
Using || for Defaults
The logical OR (||) operator can be used to assign default values if the left-hand side is falsy:
const name = userInput || 'Guest';
If `userInput` is falsy (like `null`, `undefined`, or `''`), `name` will be `'Guest'`.
Logical Short-Circuiting
JavaScript also allows you to write short if statements without `else` using the && operator.
`condition && expression;`
For example:
const isLoggedIn = true;
isLoggedIn && console.log('User is logged in');
It only prints if `isLoggedIn is true`. Equivalent to:
if (isLoggedIn) {
console.log('User is logged in');
}
Conclusion
Mastering JavaScript is about writing code that’s elegant, efficient and expressive. These techniques, from smarter `console.log()` practices and template literals to the subtle power of destructuring, spread/rest operators and short conditional logic will help you elevate your code from functional to formidable.
Think of these patterns as tools in your martial arts belt, with each one sharpening your ability to write cleaner, faster and more maintainable code. Whether you’re debugging like a pro with `console.table()` and `console.time()`, or merging arrays with surgical precision, every skill you build makes your JavaScript Kung Fu stronger.
Now go forth and code like a sensei. Your future self and your teammates will thank you for it.
Want to dive deeper into the possibilities of working with JavaScript? Read Andela’s full guide “Mastering JavaScript Proxies and Reflect for Real-World Use.”
Andela provides the world’s largest private marketplace for global remote tech talent driven by an AI-powered platform to manage the complete contract hiring lifecycle. Andela helps companies scale teams & deliver projects faster via specialized areas: App Engineering, AI, Cloud, Data & Analytics.