2011-01-12 17 views
7

Dado el siguiente código CoffeeScript:¿Por qué coffeescript genera clases como esta?

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

Esto se genera:

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; 
})(); 

Pero por qué no se genera el código más idiomática?

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

sé que CoffeeScript envuelve un montón de cosas en funciones anónimas para controlar la fuga de su alcance, pero lo que pueda haber fugas de aquí?

+3

¿Un voto cercano subjetivo y controvertido? De Verdad? Esta es una pregunta válida que pregunta por qué es necesario ajustar las funciones en una función anónima. – ryeguy

Respuesta

12

El código generado hace posible tener funciones nombradas de manera confiable en Internet Explorer. (En este caso, "Animal"). Si simplemente usa una función nombrada en el ámbito de nivel superior, entrará en conflicto con cualquier declaración var Animal = que pueda estar presente ... incluso en ámbitos inferiores, lo que impide que se haga referencia a ellos correctamente. Para evitar el error de IE, incluimos el contenedor de funciones alrededor de la definición de la clase.

+5

"Conflicto de nombre" no es exactamente la preocupación (de todos modos, estás haciendo 'var Animal ='). El problema es que nunca deberías haber nombrado la función _expressions_ para JScript. Más sobre "el error IE": http://kangax.github.com/nfe/ – matyr

2

Esto es para admitir backtraces que incluyen los nombres de las clases y no solo los nombres de las funciones cuando se lanza una excepción.

+0

¿Puedes elaborar? No estoy seguro de entender cómo funciona eso. – casablanca

+0

@casablanca - ver: http: //www.javascriptkata.com/2010/05/19/how-to-de-anonymize-your-anonymous-functions/Es la diferencia entre ver 'aonon(), aonon()' y 'func1(), func2()' en el seguimiento de la pila . –

+0

@Sean: Eso explica por qué la función se llama 'Animal', pero no parece explicar por qué está envuelta en una función anónima. – ryeguy

2

El método CoffeeScript también tiene ventajas para la minificación.

De my other answer:

Para la mayoría de las clases razonables, el cierre generada por CoffeeScript genera más pequeño de salida miniaturizada. La envoltura de cierre es de 25 bytes de sobrecarga minified, pero le ahorra de repetir el nombre de clase, ahorrando k * N bytes (k = letras en-nombre, N = num-de-refs). por ejemplo, si una clase como BoilerPlateThingyFactory tiene más de 2 métodos, la envoltura de cierre genera un código minúsculo más pequeño.



con más detalle ...

El café Código generado por el uso de un cierre le resta a:

// 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; 
}(); 

alternativas de ryeguy "idiomáticas" le resta de aplicación a este :

// 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; 
}; 

Observe cómo el nombre "Animal" existe exactamente una vez en la forma de café, y N = 2 veces en la varient "idiomática" de ryeguy. Ahora "Animal" solo tiene 6 letras, y solo hay 1 método, por lo que Coffee aquí debería perder entre 25-6 = 19 bytes. Consultando mi código minificado, es de 138 bytes a 119 bytes, para un delta de ... 19 bytes. Agregue 4 métodos más, y la ventaja cambiará a Café. Y no son solo métodos; las constantes de clase y otros tipos de ref cuentan también.

+0

La expresión 'return' separada por comas en su código uglified es interesante. En mi consola, 'return x, y, z;' parece evaluar las tres expresiones, pero solo devuelve la última. ¿Hay algún efecto al hacerlo de esta manera, aparte de hacer que el código sea más "feo"? –

+0

@JustinMorgan - ¡Usted señor ha descubierto el "operador de coma"! Es como un punto y coma, pero más poderoso ya que puede usarse como una expresión. entonces "a, b, c;" evaluará "a", luego "b", luego "c", y la expresión general tendrá el valor de "c". Es un operador que JS hereda de C, fwiw. http://en.wikipedia.org/wiki/Comma_operator –

Cuestiones relacionadas