Take a look at these two JavaScript code snippets. They look nearly identical — but do they behave the same?
Snippet 1 (without semicolon):
constpromise1=newPromise((resolve, reject) => {resolve('printing content of promise1');})(async () => {constres=await promise1; console.log('logging result ->', res);})();
Snippet 2 (with semicolon):
constpromise1=newPromise((resolve, reject) => {resolve('printing content of promise1');});(async () => {constres=await promise1; console.log('logging result ->', res);})();
What Happens When You Run Them?
❌ Snippet 1 Output:
TypeError: (intermediate value) is not a function
✅ Snippet 2 Output:
logging result -> printing content of promise1
Why Does a Single Semicolon Make Such a Big Difference?
We’ve always heard that semicolons are optional in JavaScript. So why does omitting just one lead to a runtime error here?
Let’s investigate.
What’s Really Going On?
The issue boils down to JavaScript’s Automatic Semicolon Insertion (ASI).
When you omit a semicolon, JavaScript tries to infer where it should end your statements. Usually, it does a decent job. But it’s not perfect.
In the first snippet, JavaScript parses this like so:
const promise1 = new Promise(…)(async () => { … })();
Here, it thinks you are calling the result of new Promise(…) as a function, which is not valid — hence the TypeError.
But Wait, Aren’t Semicolons Optional in JavaScript?
They are — until they’re not.
Here’s the trap:
If a new line starts with:
(
[
+ or –
/ (as in regex)
JavaScript might interpret it as part of the previous expression.
That’s what’s happening here. The async IIFE starts with (, so JavaScript assumes it continues the previous line unless you forcefully break it with a semicolon.
Key Takeaways:
ASI is not foolproof and can lead to surprising bugs.
A semicolon before an IIFE ensures it is not misinterpreted as part of the preceding line.
This is especially important when using modern JavaScript features like async/await, arrow functions, and top-level code.
Why You Should Use Semicolons Consistently
Even though many style guides (like those from Prettier or StandardJS) allow you to skip semicolons, using them consistently provides:
✅ Clarity
You eliminate ambiguity and make your code more readable and predictable.
✅ Fewer Bugs
You avoid hidden edge cases like this one, which are hard to debug — especially in production code.
✅ Compatibility
Not all environments handle ASI equally. Tools like Babel, TypeScript, or older browsers might behave differently.
Conclusion
The difference between working and broken code here is one semicolon. JavaScript’s ASI mechanism is helpful, but it can fail — especially when lines begin with characters like ( or [.
If you’re writing clean, modular, modern JavaScript, consider adding that semicolon. It’s a tiny keystroke that saves a lot of headaches.
Happy coding — and remember, when in doubt, punctuate!
A structured, six-phase approach to embedding trust into every stage of the AI lifecycle from intent definition to continuous governance.
A detailed look at how OptimaAI Trust Framework operationalizes fairness, explainability, security, monitoring, and compliance at scale.
Technical clarity on deploying bias audits, explainable AI tools, prompt-injection defenses, and drift detection in real-world production environments.
Case studies demonstrating how trust-first AI improves outcomes across industries, reducing churn prediction errors, accelerating contract analysis, and preventing costly outages.
A blueprint for leaders to transform AI from a regulatory liability into a competitive advantage, unlocking faster adoption, higher ROI, and sustained stakeholder confidence.