Zauważyłem, że w CoffeeScript, jeśli zdefiniuję funkcję za pomocą:
a = (c) -> c=1
Mogę tylko uzyskać wyrażenie funkcyjne :
var a;
a = function(c) {
return c = 1;
};
Ale osobiście często używam deklaracji funkcji , na przykład:
function a(c) {
return c = 1;
}
Używam pierwszego formularza, ale zastanawiam się, czy w CoffeeScript jest sposób na wygenerowanie deklaracji funkcji. Jeśli nie ma takiego sposobu, chciałbym wiedzieć, dlaczego CoffeeScript tego unika. Nie sądzę, by JSLint wykrzykiwał błąd dla deklaracji, o ile funkcja jest zadeklarowana na początku zakresu.
javascript
coffeescript
jslint
function-declaration
Grace Shao
źródło
źródło
class
es.Odpowiedzi:
CoffeeScript używa deklaracji funkcji (zwanych też „nazwanymi funkcjami”) tylko w jednym miejscu: w
class
definicjach. Na przykład,class Foo
kompiluje się do
var Foo; Foo = (function() { function Foo() {} return Foo; })();
Według FAQ, powód, dla którego CoffeeScript nie używa deklaracji funkcji w innym miejscu, zgodnie z FAQ :
Krótko mówiąc: nieostrożne używanie deklaracji funkcji może prowadzić do niespójności między IE (przed 9) a innymi środowiskami JS, więc CoffeeScript ich unika.
źródło
var a = function a() {};
.). Deklaracje funkcji (np.function a() {}
) Nie mają takich niespójności między przeglądarkamiTak, możesz:
hello() `function hello() {` console.log 'hello' dothings() `}`
Uciekasz przed czystym JS przez lewy przycisk `
Zwróć uwagę, że nie możesz tworzyć wcięć w treści funkcji.
Twoje zdrowie
źródło
function updateSettings() {
; do -> dothings (),}
aby umożliwić wcięcie. github.com/jashkenas/coffeescript/issues/…Jedną rzeczą, o której należy pamiętać w przypadku CoffeeScript, jest to, że zawsze możesz wrócić do JavaScript. Chociaż CoffeeScript nie obsługuje nazwanych deklaracji funkcji, zawsze możesz wrócić do JavaScript, aby to zrobić.
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; }`
Możesz także napisać dużą, grubą funkcję w CoffeeScript, a następnie użyć sztuczki z lewymi znakami, aby JavaScript wywołał drugą funkcję:
# 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); }`
źródło
Nie, nie możesz zdefiniować funkcji w skrypcie coffee i sprawić, by wygenerowała deklarację funkcji w skrypcie coffee
Nawet jeśli po prostu piszesz
-> 123
wygenerowany JS zostanie opakowany w pareny, czyniąc go tym samym wyrażeniem funkcji
(function() { return 123; });
Domyślam się, że dzieje się tak dlatego, że deklaracje funkcji są „podnoszone” na szczyt obejmującego zakresu, co spowodowałoby przerwanie logicznego przepływu źródła coffeescript.
źródło
Chociaż jest to starszy post, chciałem dodać coś do rozmowy dla przyszłych pracowników Google.
OP ma rację, ponieważ nie możemy deklarować funkcji w czystym CoffeeScript (pomijając pomysł użycia back-ticków do ucieczki czystego JS w pliku CoffeeScript).
Ale to, co możemy zrobić, to powiązać funkcję z oknem i zasadniczo otrzymać coś, co możemy nazwać tak, jakby to była nazwana funkcja. Nie twierdzę, że jest to nazwana funkcja, zapewniam sposób zrobienia tego, co wyobrażam sobie, że OP chce faktycznie zrobić (wywołać funkcję taką jak foo (param) gdzieś w kodzie) przy użyciu czystego CoffeeScript.
Oto przykład funkcji dołączonej do okna w skrypcie 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
To jest używanie Miejsc Google do zwracania informacji adresowych w celu automatycznego wypełnienia formularza.
Mamy więc fragment w aplikacji Rails, który jest ładowany na stronę. Oznacza to, że DOM jest już utworzony, a jeśli wywołamy powyższą funkcję przy początkowym załadowaniu strony (zanim wywołanie AJAX wyrenderuje częściową część), jQuery nie zobaczy elementu $ ('# property_street_address_1') (zaufaj mi - nie udało się) t).
Musimy więc opóźnić google.maps.places.Autocomplete () do momentu pojawienia się elementu na stronie.
Możemy to zrobić za pomocą wywołania zwrotnego Ajax po pomyślnym załadowaniu częściowej:
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
Więc tutaj robimy to samo, co wywołanie foo ()
źródło
Czemu? Ponieważ deklaracja funkcji jest zła. Spójrz na ten kod
function a() { return 'a'; } console.log(a()); function a() { return 'b'; } console.log(a());
Co będzie na wyjściu?
Jeśli użyjemy definicji funkcji
var a = function() { return 'a'; } console.log(a()); a = function() { return 'b'; } console.log(a());
wynik to:
źródło
Spróbuj tego:
defineFct = (name, fct)-> eval("var x = function #{name}() { return fct.call(this, arguments); }") return x
Teraz zostanie wydrukowane „prawda”:
foo = defineFct('foo', ()->'foo') console.log(foo() == foo.name)
Właściwie tego nie używam, ale czasami chciałbym, żeby funkcje kawy miały nazwy dla introspekcji.
źródło