Frage Funktionsdeklaration in CoffeeScript


Ich stelle fest, dass in CoffeeScript, wenn ich eine Funktion definiere mit:

a = (c) -> c=1

Ich kann nur das bekommen Funktionsausdruck:

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

Aber, persönlich benutze ich oft Funktionsdeklaration,beispielsweise:

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

Ich benutze das erste Formular, aber ich frage mich, ob es in CoffeeScript eine Möglichkeit gibt, eine Funktionsdeklaration zu erzeugen. Wenn es keinen solchen Weg gibt, würde ich gerne wissen, warum CoffeeScript dies vermeidet. Ich glaube nicht, dass JSLint einen Fehler für die Deklaration anprangern würde, solange die Funktion am oberen Rand des Bereichs deklariert ist.


76
2017-07-01 13:42


Ursprung


Antworten:


CoffeeScript verwendet Funktionsdeklarationen (auch "benannte Funktionen" genannt) an nur einer Stelle: class Definitionen. Zum Beispiel,

class Foo

kompiliert zu

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

Der Grund, warum CoffeeScript keine Funktionsdeklarationen an anderer Stelle verwendet, laut FAQ:

Schuld Microsoft für diesen. Ursprünglich wurde für jede Funktion, für die ein sinnvoller Name abgerufen werden konnte, eine angegeben, für die IE-Version 8 und die niedrigere Version gelten jedoch Bereichsdefinitionen, bei denen die benannte Funktion sowohl als Deklaration als auch als Ausdruck behandelt wird. Sehen Dies für mehr Informationen.

Kurz gesagt: Das unachtsame Verwenden von Funktionsdeklarationen kann zu Inkonsistenzen zwischen IE (pre-9) und anderen JS-Umgebungen führen, so dass CoffeeScript sie vermeidet.


60
2017-07-01 15:32



Ja, du kannst:

hello()

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

Du entkommst reinem JS über den Backtick `

Beachten Sie, dass Sie nicht auf Ihrem Funktionskörper einrücken können.

Prost


12
2018-03-25 00:38



Eine Sache, die Sie bei CoffeeScript beachten sollten, ist, dass Sie immer wieder auf JavaScript zurückgreifen können. Während CoffeeScript keine benannten Funktionsdeklarationen unterstützt, können Sie immer zu JavaScript zurückkehren, um dies zu tun.

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

Sie können auch eine große Fettfunktion in CoffeeScript schreiben und dann einfach den Backtick-Trick verwenden, damit JavaScript die andere Funktion aufruft:

# 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



Nein, Sie können keine Funktion im Kaffeeskript definieren und eine Funktionserklärung im Kaffeeskript erzeugen lassen

Selbst wenn du nur schreibst

-> 123

Das generierte JS wird in Parens gehüllt und ist somit ein Funktionsausdruck

(function() {
  return 123;
});

Meine Vermutung ist, dass dies daran liegt, dass Funktionsdeklarationen an den Anfang des umschließenden Bereichs gehisst werden, was den logischen Fluss der Coffeescript-Quelle aufbrechen würde.


1
2017-10-13 18:18



Während dies ein älterer Beitrag ist, wollte ich etwas für zukünftige Googler zu der Konversation hinzufügen.

OP ist richtig, da wir Funktionen im reinen CoffeeScript nicht deklarieren können (mit Ausnahme der Idee, Back-Ticks zu verwenden, um reinem JS in der CoffeeScript-Datei zu entkommen).

Aber was wir tun können, ist, die Funktion an das Fenster zu binden und im Wesentlichen mit etwas enden, das wir aufrufen können, als wäre es eine benannte Funktion. Ich sage das nicht ist Eine benannte Funktion, ich biete eine Möglichkeit, das zu tun, was ich mir vorstelle, wie OP es eigentlich machen möchte (rufen Sie eine Funktion wie foo (param) irgendwo im Code auf), indem Sie reines CoffeeScript verwenden.

Hier ist ein Beispiel für eine Funktion, die dem Fenster in coffeescript angehängt ist:

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

Mithilfe von Google Places werden Adressinformationen zurückgegeben, um ein Formular automatisch zu füllen.

So haben wir eine partielle in einer Rails-App, die auf eine Seite geladen wird. Dies bedeutet, dass das DOM bereits erstellt ist, und wenn wir die obige Funktion beim ersten Laden der Seite aufrufen (bevor der Ajax-Aufruf das partielle rendert), wird jQuery das Element $ ('# property_street_address_1') nicht sehen (vertraue mir - es hat nicht t).

Daher müssen wir die google.maps.places.Autocomplete () verzögern, bis das Element auf der Seite vorhanden ist.

Das können wir über den Ajax-Callback bei erfolgreichem Laden des Partials tun:

            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

Im Wesentlichen machen wir das gleiche wie foo ()


1
2017-10-09 16:34



Warum? weil Funktionsdeklaration ist böse. Schau dir diesen Code an

function a() {
        return 'a';
}

console.log(a());

function a() {
        return 'b';
}

console.log(a());

Was wird auf der Ausgabe sein?

b
b

Wenn wir das benutzen Funktionsdefinition

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

console.log(a());

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

console.log(a());

die Ausgabe ist:

a
b

1
2017-11-02 15:04



Versuche dies:

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

Jetzt wird das Folgende "wahr" drucken:

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

Ich benutze das eigentlich nicht, aber wünsche mir manchmal, dass Kaffee-Funktionen Namen für Introspektion hätten.


0
2017-10-21 01:05