Why does coffeescript generate such classes?

Given the following coffeescript code:

class Animal constructor: (@name) -> speak: (things) -> "My name is #{@name} and I like #{things}" 

This is generated by:

 var Animal = (function() { function Animal(name) { this.name = name; } Animal.prototype.speak = function(things) { return "My name is " + this.name + " and I like " + things; }; return Animal; })(); 

But why is this more idiomatic code not generated?

 var Animal = function Animal(name) { this.name = name; }; Animal.prototype.speak = function(things) { return "My name is " + this.name + " and I like " + things; }; 

I know coffeescript captures a lot of things in anonymous functions to control area leakage, but what can leak here?

+7
javascript coffeescript
source share
3 answers

The generated code allows you to reliably have named functions in Internet Explorer. (In this case, "Animal".) If you simply use the named function in the top-level area, it will conflict with any var Animal = declarations that may be present ... even in lower areas, not allowing them to be referenced correctly, to get around IE bug, we include a function wrapper around the class definition.

+12
source share

It supports backtracking, including class names, and not just function names when throwing an exception.

+2
source share

The CoffeeScript method also has advantages to minimize.

From my other answer :

For most reasonable classes, the closure generated by CoffeeScript generates a smaller, smaller result. The closure wrapper is 25 bytes of minimized overhead, but does not allow you to repeat the class name while maintaining k * N bytes (k = letters in the name, N = number of links). for example, if a class like BoilerPlateThingyFactory has 2+ methods, the closure wrapper generates less short code.



in details...

Code generated coffee, with closing, reduces:

 // Uglify '1.js' = 138 bytes (197 w/ whitespace): var Animal=function(){function e(e){this.name=e}return e.prototype.speak=function(e){return"My name is "+this.name+" and I like "+e},e}(); // with whitespace ("uglifyjs -b"): var Animal = function() { function e(e) { this.name = e; } return e.prototype.speak = function(e) { return "My name is " + this.name + " and I like " + e; }, e; }(); 

ryeguy an alternative "idiomatic" implementation minimizes this:

 // Uglify '2.js' = 119 bytes (150 w/ whitespace): var Animal=function(t){this.name=t};Animal.prototype.speak=function(e){return"My name is "+this.name+" and I like "+e}; // with whitespace ("uglifyjs -b"): var Animal = function(t) { this.name = t; }; Animal.prototype.speak = function(e) { return "My name is " + this.name + " and I like " + e; }; 

Note that the name "Animal" exists exactly once in the form of coffee, and N = 2 times in ryeguy "idiomatic" varient. Now "Animal" - only 6 letters, and there is only 1 method, so the coffee here should lose 25-6 = 19 bytes. Consulting with my mini-code, it is from 138 to 119 bytes, for delta ... 19 bytes. Add 4 more methods and the advantage will switch to coffee. And these are not just methods; class constants and other types of links.

+2
source share

All Articles