Je remarque que dans CoffeeScript, si je définis une fonction en utilisant:
a = (c) -> c=1
Je ne peux obtenir que expression de fonction:
var a;
a = function(c) {
return c = 1;
};
Mais personnellement, j'utilise souvent déclaration de fonction, par exemple:
function a(c) {
return c = 1;
}
J'utilise le premier formulaire, mais je me demande s'il existe un moyen dans CoffeeScript de générer une déclaration de fonction. S'il n'y a pas une telle façon, je voudrais savoir pourquoi CoffeeScript évite de faire ça. Je ne pense pas que JSLint crierait une erreur de déclaration, tant que la fonction est déclarée en haut de la portée.
CoffeeScript utilise des déclarations de fonctions (alias "fonctions nommées") en un seul endroit: class
définitions. Par exemple,
class Foo
compile en
var Foo;
Foo = (function() {
function Foo() {}
return Foo;
})();
La raison pour laquelle CoffeeScript n'utilise pas de déclarations de fonction ailleurs, selon la FAQ :
Blâmez Microsoft pour celui-ci. A l'origine, chaque fonction qui pouvait avoir un nom sensible récupéré en avait un, mais IE versions 8 et antérieures ont des problèmes de portée où la fonction nommée est traitée à la fois comme une déclaration et une expression. Voir - this pour plus d'informations.
En bref: l'utilisation imprudente des déclarations de fonctions peut entraîner des incohérences entre IE (pré-9) et d'autres environnements JS, donc CoffeeScript les évite.
Oui, vous pouvez:
hello()
`function hello() {`
console.log 'hello'
dothings()
`}`
Vous échappez pur JS via le backtick `
Notez que vous ne pouvez pas indenter votre corps de fonction.
À votre santé
Une chose à garder à l'esprit avec CoffeeScript est que vous pouvez toujours revenir à JavaScript. Bien que CoffeeScript ne prenne pas en charge les déclarations de fonctions nommées, vous pouvez toujours revenir à JavaScript pour le faire.
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; }`
Vous pouvez également écrire une grosse fonction grasse dans CoffeeScript, puis utiliser simplement l'astuce pour que JavaScript appelle l'autre fonction:
# 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); }`
Bien qu'il s'agisse d'un article plus ancien, je voulais ajouter quelque chose à la conversation pour les futurs Googlers.
OP est correct dans la mesure où nous ne pouvons pas déclarer de fonctions en pur CoffeeScript (à l'exception de l'idée d'utiliser des back-ticks pour échapper au JS pur à l'intérieur du fichier CoffeeScript).
Mais ce que nous pouvons faire, c'est lier la fonction à la fenêtre et nous retrouver essentiellement avec quelque chose que nous pouvons appeler comme s'il s'agissait d'une fonction nommée. Je ne dis pas ceci est une fonction nommée, je fournis un moyen de faire ce que j'imagine que OP veut réellement faire (appeler une fonction comme foo (param) quelque part dans le code) en utilisant du pur CoffeeScript .
Voici un exemple de fonction attachée à la fenêtre 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
Cela utilise Google Adresses pour renvoyer les informations d'adresse pour remplir automatiquement un formulaire.
Nous avons donc un partiel dans une application Rails qui est en cours de chargement dans une page. Cela signifie que le DOM est déjà créé, et si nous appelons la fonction ci-dessus lors du chargement initial de la page (avant l'appel ajax rend le partiel), jQuery ne verra pas l'élément $ ('# property_street_address_1') (croyez-moi, ce n'est pas le cas).
Nous devons donc retarder google.maps.places.Autocomplete () jusqu'à ce que l'élément soit présent sur la page.
Nous pouvons le faire via le rappel Ajax en cas de chargement réussi du partiel:
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
Donc, ici, nous faisons essentiellement la même chose que d'appeler foo ()
Pourquoi? Parce que déclaration de fonction est mauvais. Regardez ce code
function a() {
return 'a';
}
console.log(a());
function a() {
return 'b';
}
console.log(a());
Quel sera le résultat?
b
b
Si nous utilisons la définition de la fonction
var a = function() {
return 'a';
}
console.log(a());
a = function() {
return 'b';
}
console.log(a());
la sortie est:
a
b
Non, vous ne pouvez pas définir une fonction dans le script café et lui faire générer une déclaration de fonction dans le script café
Même si vous écrivez
-> 123
le JS généré sera enveloppé dans des parens, ce qui en fera une expression de fonction
(function() {
return 123;
});
Je suppose que cela est dû au fait que les déclarations de fonctions sont "hissées" en haut de la portée englobante, ce qui briserait le flux logique de la source coffeescript.
Essaye ça:
defineFct = (name, fct)->
eval("var x = function #{name}() { return fct.call(this, arguments); }")
return x
Maintenant, ce qui suit imprimera "vrai":
foo = defineFct('foo', ()->'foo')
console.log(foo() == foo.name)
Je ne l'utilise pas réellement, mais je souhaite parfois que les fonctions café aient un nom pour l'introspection.