2012-01-22 14 views

Respuesta

140

No, esa no es la regla que usaría.

El mayor de casos de uso que he encontrado para la grasa de flecha en la definición de los métodos es cuando se quiere utilizar un método como llamada de retorno y que los campos de instancia referencias de métodos:

class A 
    constructor: (@msg) -> 
    thin: -> alert @msg 
    fat: => alert @msg 

x = new A("yo") 
x.thin() #alerts "yo" 
x.fat() #alerts "yo" 

fn = (callback) -> callback() 

fn(x.thin) #alerts "undefined" 
fn(x.fat) #alerts "yo" 
fn(-> x.thin()) #alerts "yo" 

Como se ve, es posible que tenga problemas al pasar una referencia al método de una instancia como una devolución de llamada si no utiliza la flecha adiposa. Esto se debe a que la flecha grasa vincula la instancia del objeto a this, mientras que la flecha delgada no, por lo que los métodos de flecha delgada llamados devoluciones de llamada como los anteriores no pueden acceder a los campos de la instancia como @msg ni llamar a otros métodos de instancia. La última línea es una solución alternativa para los casos en los que se ha utilizado la flecha delgada.

+2

¿Qué hace cuando quiere usar el 'this' que se llamaría desde la flecha delgada, pero también las variables de instancia que obtendría? con la flecha gordo? –

+0

Como dije "La última línea hay una solución alternativa para casos donde se ha utilizado la flecha delgada". – nicolaskruchten

+0

Creo que malinterpretaste mi pregunta. Supongamos que el alcance predeterminado de la devolución de llamada tiene 'this' establecido en una variable que quiero usar. Sin embargo, también quiero hacer referencia a un método de clase, por lo que quiero 'this' para referirse a la clase también. Solo puedo elegir entre una asignación para 'this', entonces, ¿cuál es la mejor manera de poder usar ambas variables? –

8

Normalmente, -> está bien.

class Foo 
    @static: -> this 
    instance: -> this 

alert Foo.static() == Foo # true 

obj = new Foo() 
alert obj.instance() == obj # true 

Nota cómo el método estático devolver el objeto de clase de la instancia this y devuelve el objeto de instancia para this.

Lo que está sucediendo es que la sintaxis de invocación proporciona el valor de this. En este código:

foo.bar() 

foo será el contexto de la función bar() por defecto. Por lo tanto, simplemente funciona como quieras. Solo necesita la flecha adiposa cuando llama a estas funciones de alguna otra manera que no usa la sintaxis de puntos para la invocación.

# Pass in a function reference to be called later 
# Then later, its called without the dot syntax, causing `this` to be lost 
setTimeout foo.bar, 1000 

# Breaking off a function reference will lose it's `this` too. 
fn = foo.bar 
fn() 

En ambos casos, usar una flecha adiposa para declarar esa función permitiría que funcionen. Pero a menos que esté haciendo algo extraño, generalmente no es necesario.

Así que use -> hasta que realmente necesite => y nunca use => de manera predeterminada.

+1

Esto fallará si lo hace: 'x = obj.instance; alerta x() == obj # false! ' – nicolaskruchten

+2

Por supuesto que sí, pero eso estaría en" hacerlo mal ". Ahora he editado mi respuesta y explico cuándo se necesitaría '=>' en los métodos estáticos/de instancia de una clase. –

+0

Nitpick: '// no es un comentario de CoffeeScript', mientras que' # es un comentario de CoffeeScript'. – nicolaskruchten

10

Un punto no mencionado en otras respuestas que es importante tener en cuenta es que el enlace funciona con la flecha adiposa cuando no es necesario puede dar lugar a resultados no deseados como en este ejemplo con una clase que llamaremos DummyClass.

class DummyClass 
    constructor :() -> 
    some_function :() -> 
     return "some_function" 

    other_function :() => 
     return "other_function" 

dummy = new DummyClass() 
dummy.some_function() == "some_function"  # true 
dummy.other_function() == "other_function" # true 

En este caso las funciones de hacer exactamente lo que cabría esperar, y no parece haber ninguna pérdida para el uso de la flecha de grasa, pero lo que sucede cuando modificamos el prototipo DummyClass después de que ya se ha definido (por ejemplo,cambiando algunos alerta o cambiar la salida de un registro):

DummyClass::some_function = -> 
    return "some_new_function" 

DummyClass::other_function = -> 
    return "other_new_function" 

dummy.some_function() == "some_new_function" # true 
dummy.other_function() == "other_new_function" # false 
dummy.other_function() == "other_function"  # true 

Como podemos ver anulando nuestra función previamente definida del prototipo causa some_function a sobrescribir correctamente, pero other_function sigue siendo la misma en los casos en forma de grasa flecha ha causado other_function de la clase que se une a todas las instancias para casos no se referirá de nuevo a su clase para encontrar una función

flecha
DummyClass::other_function = => 
    return "new_other_new_function" 

dummy.other_function() == "new_other_new_function" # false 

second_dummy = new DummyClass() 
second_dummy.other_function() == "new_other_new_function" # true 

Incluso la grasa no va a funcionar como grasa flecha única hace que la función que quedará vinculado a nuevas instancias (que ganan las nuevas funciones como uno esperaría).

Sin embargo, esto genera algunos problemas. Si necesitamos una función (por ejemplo, en el caso de cambiar una función de registro a un cuadro de salida o algo así), funcionará en todas las instancias existentes (incluidos los controladores de eventos) [como tal no se pueden usar flechas gordas en la definición original], pero aún necesitamos acceso a atributos internos en un manejador de eventos [la razón exacta por la que usamos flechas gordas, no flechas delgadas].

Bueno, la forma más simple de lograr esto es simplemente incluir dos funciones en la definición de clase original, una definida con una flecha delgada que hace las operaciones que desea ejecutar y otra definida con una flecha adiposa que no hace más que llamar a la primera función, por ejemplo:

class SomeClass 
    constructor :() -> 
     @data = 0 
    _do_something :() -> 
     return @data 
    do_something :() => 
     @_do_something() 

something = new SomeClass() 
something.do_something() == 0  # true 
event_handler = something.do_something 
event_handler() == 0    # true 

SomeClass::_do_something = -> return @data + 1 

something.do_something() == 1  # true 
event_handler() == 1    # true 

Así que cuando utilizar flechas finas/grasa puede resumirse bastante fácil de cuatro maneras:

  1. flecha delgada funciones se deberían utilizar únicamente cuando las condiciones de ambos son mett:

    • El método nunca se pasará por referencia, incluyendo event_handlers, p. nunca tiene un caso como: some_reference = some_instance.some_method; some_reference()
    • y el método debe ser universal sobre todas las instancias de modo que si la función prototipo cambia también lo hace el método sobre todas las instancias
  2. grasa flecha debe ser utilizada cuando se cumple la siguiente condición funciones por sí solos:

    • el método debe ser obligado precisamente a la instancia en la creación de la instancia y siguen vinculados de forma permanente incluso si cambia la definición de función para el prototipo, esto incluye todos los casos en que la función debe ser un controlador de eventos y el comportamiento controlador de eventos debe ser consistente
  3. Fat función flecha que llama directamente a una función flecha delgada se debe utilizar cuando se cumplan las siguientes condiciones:

    • Se requiere que el método a ser llamado por referencia, tal como un controlador de eventos
    • Y la funcionalidad puede cambiar en el futuro que afecta a las instancias existentes mediante la sustitución de la función de flecha delgada
  4. función flecha delgada que llama directamente una flecha de grasa (no demonstrat función ed) se debe utilizar cuando se cumplen las siguientes condiciones:

    • La función flecha grasa debe ser siempre asociado a la instancia
    • pero la función flecha delgada puede cambiar (incluso a una nueva función que no hace Nunca se necesita utilizar la función de grasa flecha originales)
    • Y la función de flecha delgada para ser pasado por referencia

en todos estos planteamientos, debe tenerse en cuenta en el caso en el prototipo las funciones pueden cambiarse si el comportamiento de instancias específicas se comportará correctamente, por ejemplo, aunque una función se define con una flecha adherente, su comportamiento puede no ser coherente dentro de una instancia si llama a un método que se cambia dentro del prototipo

5

un ejemplo para unstanding la flecha grasa

no

obras: (@canvas indefinidos)

class Test 
    constructor: -> 
    @canvas = document.createElement 'canvas' 
    window.addEventListener 'resize', -> 
     @canvas.width = window.innerWidth 
     @canvas.height = window.innerHeight 

obras: (@canvas definidos)

class Test 
    constructor: -> 
    @canvas = document.createElement 'canvas' 
    window.addEventListener 'resize', => 
     @canvas.width = window.innerWidth 
     @canvas.height = window.innerHeight 
Cuestiones relacionadas