Pertanyaan Deklarasi fungsi dalam CoffeeScript


Saya perhatikan itu di CoffeeScript, jika saya mendefinisikan fungsi menggunakan:

a = (c) -> c=1

Saya hanya bisa mendapatkan ekspresi fungsi:

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

Tapi, secara pribadi saya sering menggunakannya deklarasi fungsi,sebagai contoh:

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

Saya memang menggunakan formulir pertama, tapi saya bertanya-tanya apakah ada cara di CoffeeScript menghasilkan deklarasi fungsi. Jika tidak ada cara seperti itu, saya ingin tahu mengapa CoffeeScript tidak melakukan hal ini. Saya tidak berpikir JSLint akan meneriakkan kesalahan untuk deklarasi, asalkan fungsi tersebut dideklarasikan di bagian atas ruang lingkup.


76
2017-07-01 13:42


asal


Jawaban:


CoffeeScript menggunakan deklarasi fungsi (alias "fungsi bernama") hanya dalam satu tempat: class definisi. Contohnya,

class Foo

dikompilasi ke

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

Alasan mengapa CoffeeScript tidak menggunakan deklarasi fungsi di tempat lain, menurut FAQ:

Salahkan Microsoft untuk yang satu ini. Awalnya setiap fungsi yang bisa memiliki nama yang masuk akal diambil untuk itu diberikan satu, tetapi versi IE 8 dan ke bawah memiliki masalah pelingkupan di mana fungsi bernama diperlakukan baik sebagai deklarasi dan ekspresi. Lihat ini untuk informasi lebih lanjut.

Singkatnya: Menggunakan deklarasi fungsi secara sembarangan dapat menyebabkan inkonsistensi antara IE (pra-9) dan lingkungan JS lainnya, sehingga CoffeeScript mengesampingkannya.


60
2017-07-01 15:32



Ya kamu bisa:

hello()

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

Anda melarikan diri dari JS murni melalui backtick `

Perhatikan bahwa Anda tidak dapat mengisi pada tubuh fungsi Anda.

Tepuk tangan


12
2018-03-25 00:38



Satu hal yang perlu diingat dengan CoffeeScript adalah Anda selalu dapat menendang kembali ke JavaScript. Meskipun CoffeeScript tidak mendukung deklarasi fungsi bernama, Anda selalu dapat kembali ke JavaScript untuk melakukannya.

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

Anda juga dapat menulis fungsi gemuk besar di CoffeeScript dan kemudian hanya menggunakan trik backticks untuk memiliki JavaScript memanggil fungsi lain:

# 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



Tidak, Anda tidak dapat mendefinisikan fungsi dalam skrip kopi dan membuatnya membuat deklarasi fungsi dalam skrip kopi

Bahkan jika kamu hanya menulis

-> 123

JS yang dihasilkan akan dibungkus dengan orang tua, sehingga membuatnya menjadi ekspresi fungsi

(function() {
  return 123;
});

Tebakan saya adalah bahwa ini adalah karena deklarasi fungsi mendapatkan "mengangkat" ke bagian atas lingkup melampirkan yang akan memecah aliran logis dari sumber coffeescript.


1
2017-10-13 18:18



Meskipun ini adalah pos lama, saya ingin menambahkan sesuatu ke percakapan untuk Karyawan Google di masa mendatang.

OP benar karena kami tidak dapat mendeklarasikan fungsi dalam CoffeeScript murni (tidak termasuk ide menggunakan kutu belakang untuk keluar dari JS murni di dalam file CoffeeScript).

Tapi apa yang bisa kita lakukan adalah mengikat fungsi ke jendela dan pada dasarnya berakhir dengan sesuatu yang dapat kita sebut seolah-olah itu adalah fungsi bernama. Saya tidak menyatakan ini aku s fungsi bernama, saya menyediakan cara untuk melakukan apa yang saya bayangkan OP ingin benar-benar lakukan (memanggil fungsi seperti foo (param) di suatu tempat dalam kode) menggunakan kopi murni.

Berikut ini contoh fungsi yang dilekatkan pada jendela dalam kopi:

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

Ini menggunakan Google Places untuk mengembalikan informasi alamat untuk secara otomatis mengisi formulir.

Jadi kami memiliki sebagian di aplikasi Rails yang sedang dimuat ke halaman. Ini berarti DOM sudah dibuat, dan jika kita memanggil fungsi di atas pada pemuatan halaman awal (sebelum ajax memanggil sebagian), jQuery tidak akan melihat elemen $ ('# property_street_address_1') (percaya saya - tidak t).

Jadi kita perlu menunda google.maps.places.Autocomplete () hingga setelah elemen hadir di halaman.

Kita dapat melakukan ini melalui callback Ajax pada pemuatan sebagian yang berhasil:

            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

Jadi di sini, pada dasarnya, kami melakukan hal yang sama dengan memanggil foo ()


1
2017-10-09 16:34



Mengapa? Karena deklarasi fungsi jahat. Lihatlah kode ini

function a() {
        return 'a';
}

console.log(a());

function a() {
        return 'b';
}

console.log(a());

Apa yang akan ada di output?

b
b

Jika kami menggunakan definisi fungsi

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

console.log(a());

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

console.log(a());

outputnya adalah:

a
b

1
2017-11-02 15:04



Coba ini:

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

Sekarang yang berikut ini akan mencetak "benar":

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

Saya sebenarnya tidak menggunakan ini, tetapi kadang-kadang berharap fungsi kopi memiliki nama untuk introspeksi.


0
2017-10-21 01:05