Pregunta Declaración de función en CoffeeScript


Noté que en CoffeeScript, si defino una función usando:

a = (c) -> c=1

Solo puedo obtener el expresión de función:

var a;
a = function(c) {
    return c = 1;
};

Pero, personalmente, a menudo uso declaración de función,por ejemplo:

function a(c) {
    return c = 1;
}

Utilizo el primer formulario, pero me pregunto si hay una manera en CoffeeScript de generar una declaración de función. Si no hay tal forma, me gustaría saber por qué CoffeeScript evita hacer esto. No creo que JSLint gritara un error para la declaración, siempre y cuando la función se declare en la parte superior del alcance.


76
2017-07-01 13:42


origen


Respuestas:


CoffeeScript usa declaraciones de funciones (también conocidas como "funciones nombradas") en un solo lugar: class definiciones. Por ejemplo,

class Foo

compila a

var Foo;
Foo = (function() {
  function Foo() {}
  return Foo;
})();

El motivo por el que CoffeeScript no utiliza declaraciones de funciones en otro lugar, de acuerdo con Preguntas más frecuentes:

Culpar a Microsoft por este. Originalmente cada función que podía tener un nombre razonable recuperado se le dio una, pero las versiones IE 8 y anteriores tienen problemas de alcance donde la función nombrada se trata como una declaración y una expresión. Ver esta para más información.

En resumen: el uso descuidado de las declaraciones de funciones puede provocar inconsistencias entre IE (pre-9) y otros entornos JS, por lo que CoffeeScript las evita.


60
2017-07-01 15:32



Sí tu puedes:

hello()

`function hello() {`
console.log 'hello'
dothings()
`}`

Te escapas JS puro a través del backtick `

Tenga en cuenta que no puede aplicar sangría en su cuerpo de función.

Aclamaciones


12
2018-03-25 00:38



Una cosa a tener en cuenta con CoffeeScript es que siempre puedes volver a JavaScript. Si bien CoffeeScript no es compatible con las declaraciones de función nombradas, siempre puede volver a utilizar JavaScript para hacerlo.

http://jsbin.com/iSUFazA/11/edit

# http://jsbin.com/iSUFazA/11/edit
# You cannot call a variable function prior to declaring it!
# alert csAddNumbers(2,3) # bad!

# CoffeeScript function
csAddNumbers = (x,y) -> x+y

# You can call a named function prior to
# delcaring it
alert "Calling jsMultiplyNumbers: " + jsMultiplyNumbers(2,3) # ok!

# JavaScript named function
# Backticks FTW!
`function jsMultiplyNumbers(x,y) { return x * y; }`

También puede escribir una función grande en CoffeeScript y luego usar el truco de las teclas de retroceso para que JavaScript llame a la otra función:

# Coffeescript big function
csSomeBigFunction = (x,y) ->
   z = x + y
   z = z * x * y
   # do other stuff
   # keep doing other stuff

# Javascript named function wrapper
`function jsSomeBigFunction(x,y) { return csSomeBigFunction(x,y); }`

6
2017-10-27 18:47



No, no puedes definir una función en Coffee Script y hacer que genere una declaración de función en Coffee Script

Incluso si solo escribes

-> 123

el JS generado estará envuelto en parens, convirtiéndolo así en una expresión de función

(function() {
  return 123;
});

Mi suposición es que esto se debe a que las declaraciones de funciones se "alzan" al principio del alcance adjunto, lo que rompería el flujo lógico de la fuente del coffeescript.


1
2017-10-13 18:18



Si bien esta es una publicación anterior, quería agregar algo a la conversación para futuros Googlers.

OP es correcto en que no podemos declarar funciones en CoffeeScript puro (excluyendo la idea de usar back-ticks para escapar de JS puro dentro del archivo CoffeeScript).

Pero lo que podemos hacer es vincular la función a la ventana y esencialmente terminar con algo que podemos llamar como si fuera una función nombrada. No estoy diciendo esto es una función nombrada, estoy proporcionando una manera de hacer lo que imagino que OP quiere hacer realmente (llamar a una función como foo (param) en algún lugar del código) utilizando CoffeeScript puro.

Aquí hay un ejemplo de una función adjunta a la ventana en coffeescript:

window.autocomplete_form = (e) ->
    autocomplete = undefined
    street_address_1 = $('#property_street_address_1')
    autocomplete = new google.maps.places.Autocomplete(street_address_1[0], {})
    google.maps.event.addListener autocomplete, "place_changed", ->
        place = autocomplete.getPlace()

        i = 0

        while i < place.address_components.length
            addr = place.address_components[i]
            st_num = addr.long_name if addr.types[0] is "street_number"
            st_name = addr.long_name if addr.types[0] is "route"

            $("#property_city").val addr.long_name if addr.types[0] is "locality"
            $("#property_state").val addr.short_name if addr.types[0] is "administrative_area_level_1"
            $("#property_county").val (addr.long_name).replace(new RegExp("\\bcounty\\b", "gi"), "").trim() if addr.types[0] is "administrative_area_level_2"
            $("#property_zip_code").val addr.long_name if addr.types[0] is "postal_code"
            i++

        if st_num isnt "" and (st_num?) and st_num isnt "undefined"
            street1 = st_num + " " + st_name
        else
            street1 = st_name

        street_address_1.blur()
        setTimeout (->
            street_address_1.val("").val street1
            return
            ), 10
        street_address_1.val street1
        return

Esto está usando Google Places para devolver información de la dirección para rellenar automáticamente un formulario.

Entonces, tenemos un parcial en una aplicación de Rails que se está cargando en una página. Esto significa que el DOM ya está creado, y si llamamos a la función anterior en la carga de la página inicial (antes de que la llamada ajax represente el parcial), jQuery no verá el elemento $ ('# property_street_address_1') (confía en mí, no lo hizo t).

Entonces, debemos retrasar google.maps.places.Autocomplete () hasta que el elemento esté presente en la página.

Podemos hacer esto a través de la devolución de llamada de Ajax en la carga exitosa del parcial:

            url = "/proposal/"+property_id+"/getSectionProperty"
            $("#targ-"+target).load url, (response, status, xhr) ->
                if status is 'success'
                    console.log('Loading the autocomplete form...')
                    window.autocomplete_form()
                    return

            window.isSectionDirty = false

Aquí, básicamente, estamos haciendo lo mismo que llamar a foo ()


1
2017-10-09 16:34



¿Por qué? Porque declaración de función es malvado Mira este código

function a() {
        return 'a';
}

console.log(a());

function a() {
        return 'b';
}

console.log(a());

¿Qué estará en la salida?

b
b

Si usamos el definición de función

var a = function() {
        return 'a';
}

console.log(a());

a = function() {
        return 'b';
}

console.log(a());

la salida es:

a
b

1
2017-11-02 15:04



Prueba esto:

defineFct = (name, fct)->
  eval("var x = function #{name}() { return fct.call(this, arguments); }")
  return x

Ahora lo siguiente imprimirá "verdadero":

foo = defineFct('foo', ()->'foo')
console.log(foo() == foo.name)

Realmente no uso esto, pero a veces deseo que las funciones de café tengan nombres para la introspección.


0
2017-10-21 01:05