80

CoffeeScriptで、次を使用して関数を定義すると、次のことに気付きます。

a = (c) -> c=1

関数式しか取得できません:

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

しかし、個人的には、関数宣言をよく使用します。たとえば、次のようになります。

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

私は最初の形式を使用しますが、CoffeeScriptに関数宣言を生成する方法があるかどうか疑問に思っています。そのような方法がない場合は、CoffeeScriptがこれを回避する理由を知りたいと思います。関数がスコープの一番上で宣言されている限り、JSLintが宣言のエラーを叫ぶことはないと思います。

4

7 に答える 7

61

CoffeeScriptは、定義という1つの場所で関数宣言(別名「名前付き関数」)を使用しclassます。例えば、

class Foo

にコンパイルします

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

FAQによると、CoffeeScriptが他の場所で関数宣言を使用しない理由:

これはマイクロソフトのせいです。元々、意味のある名前を取得できるすべての関数に1つが与えられていましたが、IEバージョン8以下では、名前付き関数が宣言と式の両方として扱われるというスコープの問題があります。詳細については、これを参照してください。

つまり、関数宣言を不注意に使用すると、IE(pre-9)と他のJS環境との間に不整合が生じる可能性があるため、CoffeeScriptはそれらを避けます。

于 2011-07-01T15:32:01.833 に答える
12

はい、できます:

hello()

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

バッククォートを介して純粋なJSをエスケープします`

関数本体をインデントできないことに注意してください。

乾杯

于 2014-03-25T00:38:02.730 に答える
6

CoffeeScriptで覚えておくべきことの1つは、いつでもJavaScriptに戻ることができるということです。CoffeeScriptは名前付き関数宣言をサポートしていませんが、いつでもJavaScriptに戻ってそれを行うことができます。

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

また、CoffeeScriptで大きな太った関数を記述し、バックティックトリックを使用してJavaScriptに他の関数を呼び出させることもできます。

# 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); }`
于 2013-10-27T18:47:51.033 に答える
1

いいえ、Coffee Scriptで関数を定義して、CoffeeScriptで関数宣言を生成させることはできません。

書いただけでも

-> 123

生成されたJSは括弧で囲まれるため、関数式になります

(function() {
  return 123;
});

私の推測では、これは、関数宣言が囲んでいるスコープの先頭に「引き上げられ」、Coffeescriptソースの論理フローを分割するためです。

于 2011-10-13T18:18:00.227 に答える
1

これは古い投稿ですが、将来のGoogle社員のために会話に何かを追加したいと思いました。

OPは、純粋なCoffeeScriptで関数を宣言できないという点で正しいです(CoffeeScriptファイル内の純粋なJSをエスケープするためにバックティックを使用するという考えを除く)。

しかし、私たちにできることは、関数をウィンドウにバインドすることであり、基本的に、名前付き関数であるかのように呼び出すことができるものになります。これ名前付き関数であるとは言っていません。純粋なCoffeeScriptを使用して、OPが実際に実行したいこと(コードのどこかでfoo(param)のような関数を呼び出す)を実行する方法を提供しています。

以下は、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

これは、Googleプレイスを使用して住所情報を返し、フォームに自動入力します。

つまり、ページにロードされているRailsアプリにパーシャルがあります。これは、DOMがすでに作成されていることを意味し、最初のページの読み込み時に(ajax呼び出しが部分をレンダリングする前に)上記の関数を呼び出すと、jQueryは$('#property_street_address_1')要素を認識しません(信頼してください-それはしませんでした ' t)。

そのため、要素がページに表示されるまでgoogle.maps.places.Autocomplete()を遅らせる必要があります。

パーシャルのロードが成功すると、Ajaxコールバックを介してこれを行うことができます。

            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

したがって、ここでは、基本的に、foo()を呼び出すのと同じことを行っています。

于 2014-10-09T16:34:48.187 に答える
1

なんで?関数宣言は悪だからです。このコードを見てください

function a() {
        return 'a';
}

console.log(a());

function a() {
        return 'b';
}

console.log(a());

出力には何が表示されますか?

b
b

関数定義を使用する場合

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

console.log(a());

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

console.log(a());

出力は次のとおりです。

a
b
于 2015-11-02T15:04:28.633 に答える
0

これを試して:

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

これで、次のように「true」が出力されます。

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

私は実際にはこれを使用しませんが、コーヒー機能に内省の名前が付いていることを望む場合があります。

于 2014-10-21T01:05:44.443 に答える