I’ve been coding in CoffeeScript for more than two years and have found it boosts my productivity significantly. Writing CoffeeScript allows me to write cleaner code with fewer errors, and debugging is a breeze thanks to source map support.

Lately, I’ve been experimenting with ES6 using Babel and I must say, I’m quite impressed. In this article, I’ll share my insights on ES6 from the viewpoint of someone transitioning from CoffeeScript, focusing on its strengths and what I believe it still lacks.
Syntactically Significant Indentation: Friend or Foe?
My relationship with CoffeeScript’s syntactically significant indentation has been somewhat complicated. When it works seamlessly, it feels incredibly efficient, offering a minimalistic syntax. However, encountering bugs due to incorrect indentation (which does happen) can be frustrating, making the advantages seem less appealing.
| |
These issues often arise when dealing with nested statements within a code block, where accidental indentation of a statement can lead to problems. Fatigue can play a role, but I believe such errors are more frequent in CoffeeScript.

Initially, when I began using ES6, I wasn’t sure how I’d feel about the change. Surprisingly, it felt incredibly natural to revert to using curly braces. Modern editors enhance the experience by automatically closing braces, further simplifying the process. This shift felt like stepping into a familiar and organized world compared to the perceived “magic” of CoffeeScript.
| |
Personally, I advocate for eliminating semicolons. I believe that if they’re not essential, they should be removed. I find them aesthetically unpleasing and an unnecessary typing burden.
Class Support
ES6’s class support is truly remarkable, offering a familiar experience for those transitioning from CoffeeScript. Let’s compare their syntax with a simple example:
ES6 Class
| |
CoffeeScript Class
| |
Initial Thoughts

One noticeable difference is that ES6 remains more verbose compared to CoffeeScript. CoffeeScript’s support for automatic assignment of instance variables within the constructor is a convenient feature:
| |
This translates to the following in ES6:
| |
While not a major issue, this more explicit syntax in ES6 enhances readability. Another minor omission is the absence of the @ shortcut for this, a feature I enjoyed from my Ruby experience, though not a significant drawback. Overall, the experience feels comfortable, and I find myself preferring the ES6 syntax for defining methods.
Supercharged with Super
There’s a slight difference in how super is handled in ES6. CoffeeScript adopts the Ruby approach (“send a message to the superclass method with the same name”), while ES6 only permits a “naked” super within the constructor, following a more traditional Java-like approach where super refers to the superclass instance.
The Return of Return
CoffeeScript allows implicit returns for concise code like:
| |
However, there’s a small chance of getting “foo” back when calling foo(). ES6 enforces explicit returns using the return keyword:
| |
While generally beneficial, I still occasionally forget to include it, resulting in unexpected undefined returns. One exception is with Arrow Functions, which provide implicit returns for single-line statements:
| |
This can be useful but slightly confusing, as adding curly braces necessitates the use of return:
| |
However, the logic remains consistent: using curly braces implies multiple lines, making it essential to clearly indicate the return value.
ES6 Class Syntax Enhancements
While CoffeeScript offers some syntactical conveniences for defining classes, ES6 also introduces its own set of useful features.
Getters and Setters
ES6 provides robust support for encapsulation through getters and setters, as demonstrated below:
| |
The getter ensures that accessing bananaStore.bananas only returns ripe bananas. This is a significant improvement over CoffeeScript, where achieving similar functionality would require a getter method like bananaStore.getBananas(). ES6’s approach aligns with typical JavaScript property access, enhancing consistency and readability.
Setters are equally valuable, allowing data cleaning or exception handling for invalid input. This will be familiar to those with a Ruby background.
However, excessive use of getters and setters is discouraged. Use them strategically when encapsulation provides tangible benefits. For instance, directly exposing a simple boolean property like isEditable might be more efficient if it doesn’t compromise anything.
Static Methods
ES6 supports static methods, enabling the following unconventional approach:
| |
While purists might disapprove due to new being a reserved word, this works in modern environments. However, it’s not recommended for production code!
Unfortunately, the lack of support for static properties in ES6 requires workarounds for defining class constants, which can be cumbersome:
| |
A ES7 Proposal aims to implement declarative instance and class properties for a more elegant solution:
| |
CoffeeScript already handles this gracefully:
| |
String Interpolation: Finally Here!
JavaScript finally embraces string interpolation!
| |
Coming from CoffeeScript/Ruby, this syntax might feel somewhat odd. My Ruby background, where backticks execute system commands, initially made it feel unusual. The use of the dollar sign might seem slightly dated as well, but that could be subjective.

The chosen syntax was likely influenced by backward compatibility constraints, preventing the implementation of CoffeeScript-style interpolation. "What a #{expletive} shame".
Arrow Functions: Concise and Lexically Scoped
Arrow functions are a given in CoffeeScript, and ES6 closely mirrors their syntax. This provides a concise syntax and lexically scoped this, eliminating the need for workarounds required in ES5:
| |
The ES6 equivalent is cleaner:
| |
Notice the omission of parentheses around the unary callback, a welcome change!
Enhanced Object Literals
ES6 introduces significant improvements to object literals, expanding their capabilities.
Dynamic Property Names
CoffeeScript 1.9.1 introduced a convenient way to define dynamic property names:
| |
This is a vast improvement over previous workarounds:
| |
ES6 offers an alternative syntax, which, while not groundbreaking, is still quite nice:
| |
Nifty Shortcuts
Borrowed from CoffeeScript, this handy feature might be unfamiliar to some:
| |
The obj now contains { foo: 'foo', bar: 'bar' }, a useful shortcut worth remembering.
Class-like Capabilities
Object literals in ES6 can now perform many class-like actions, including:
| |
While its practicality might be debatable, it highlights the expanded capabilities of object literals. However, defining static methods remains exclusive to classes.
For-Loops: A Potential Source of Confusion
ES6’s for-loop syntax might cause some initial confusion for CoffeeScript users due to the reversed meaning of for-of and for-in:
ES6
| |
CoffeeScript
| |
Should You Make the Switch to ES6?
I’m currently engaged in a large Node.js project using 100% CoffeeScript and remain satisfied with its productivity. The only feature I envy in ES6 is getters and setters.
However, using ES6 today still has its challenges. While the latest Node.js version provides near-complete ES6 features support, older versions and browser compatibility remain less ideal. Using Babel is an option but requires integration into your workflow.
Despite these hurdles, I anticipate ES6 gaining significant traction in the coming years, with even more exciting developments in ES7.
What excites me most about ES6 is how it elevates “plain old JavaScript” to a level of user-friendliness and power comparable to CoffeeScript. This is fantastic news for JavaScript developers, as ES6 breathes new life and excitement into the language.