Javascript CoffeeScript 中的函数声明

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6548750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:15:07  来源:igfitidea点击:

Function declaration in CoffeeScript

javascriptcoffeescriptjslintfunction-declaration

提问by Grace Shao

I notice that in CoffeeScript, if I define a function using:

我注意到在 CoffeeScript 中,如果我使用以下方法定义一个函数:

a = (c) -> c=1

I can only get the function expression:

我只能得到函数表达式

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

But, personally I often use function declaration,for example:

但是,我个人经常使用函数声明,例如:

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

I do use the first form, but I'm wondering if there is a way in CoffeeScript generating a function declaration. If there is no such way, I would like to know why CoffeeScript avoid doing this. I don't think JSLint would holler an error for declaration, as long as the function is declared at the top of the scope.

我确实使用了第一种形式,但我想知道 CoffeeScript 中是否有生成函数声明的方法。如果没有这样的方法,我想知道为什么 CoffeeScript 避免这样做。我不认为 JSLint 会在声明时出现错误,只要函数是在作用域的顶部声明的。

采纳答案by Trevor Burnham

CoffeeScript uses function declarations (aka "named functions") in just one place: classdefinitions. For instance,

CoffeeScript 只在一个地方使用函数声明(又名“命名函数”):class定义。例如,

class Foo

compiles to

编译为

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

The reason CoffeeScript doesn't use function declarations elsewhere, according to the FAQ:

根据常见问题解答,CoffeeScript 不在其他地方使用函数声明的原因:

Blame Microsoft for this one. Originally every function that could have a sensible name retrieved for it was given one, but IE versions 8 and down have scoping issues where the named function is treated as both a declaration and an expression. See thisfor more information.

将这一点归咎于微软。最初,每个可以为其检索合理名称的函数都被赋予一个,但是 IE 8 及以下版本存在范围界定问题,其中命名函数被视为声明和表达式。有关更多信息,请参阅内容。

In short: Using function declarations carelessly can lead to inconsistencies between IE (pre-9) and other JS environments, so CoffeeScript eschews them.

简而言之:不小心使用函数声明会导致 IE(9 之前)和其他 JS 环境之间的不一致,因此 CoffeeScript 避开它们。

回答by Zaid Daghestani

Yes you can:

是的你可以:

hello()

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

You escape pure JS via the backtick `

您可以通过反引号 ` 转义纯 JS

Note that you can't indent on your function body.

请注意,您不能在函数体上缩进。

Cheers

干杯

回答by mattmc3

One thing to keep in mind with CoffeeScript is that you can always kick back to JavaScript. While CoffeeScript doesn't support named function declarations, you can always drop back to JavaScript to do it.

使用 CoffeeScript 时要记住的一件事是,您始终可以回到 JavaScript。虽然 CoffeeScript 不支持命名函数声明,但您始终可以退回到 JavaScript 来执行此操作。

http://jsbin.com/iSUFazA/11/edit

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

You can also write a big fat function in CoffeeScript and then just use the backticks trick to have JavaScript call the other function:

您还可以在 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); }`

回答by Tomasz Jakub Rup

Why? Because function declarationis evil. Look at this code

为什么?因为函数声明是邪恶的。看看这个代码

function a() {
        return 'a';
}

console.log(a());

function a() {
        return 'b';
}

console.log(a());

What will be on the output?

输出会是什么?

b
b

If we use the function definition

如果我们使用函数定义

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

console.log(a());

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

console.log(a());

the output is:

输出是:

a
b

回答by notaceo

While this is an older post, I wanted to add something to the conversation for future Googlers.

虽然这是一篇较旧的帖子,但我想为未来的 Google 员工在对话中添加一些内容。

OP is correct in that we cannot declare functions in pure CoffeeScript (excluding the idea of using back-ticks to escape pure JS inside the CoffeeScript file).

OP 是正确的,因为我们不能在纯 CoffeeScript 中声明函数(不包括在 CoffeeScript 文件中使用反引号来转义纯 JS 的想法)。

But what we can do is bind the function to the window and essentially end up with something we can call as though it was a named function. I am not stating this isa named function, I'm providing a way to do what I imagine OP wants to actually do (call a function like foo(param) somewhere in the code) using pure CoffeeScript.

但是我们可以做的是将函数绑定到窗口,并最终得到一些我们可以调用的东西,就好像它是一个命名函数一样。我并不是说这一个命名函数,我提供了一种方法来使用纯 CoffeeScript 来执行我想象的 OP 想要实际执行的操作(在代码中的某处调用像 foo(param) 这样的函数)。

Here is an example of a function attached to the window in coffeescript:

下面是一个在 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

This is using Google Places to return address information to auto-populate a form.

这是使用 Google Places 返回地址信息以自动填充表单。

So we have a partial in a Rails app which is being loaded into a page. This means the DOM is already created, and if we call the function above on initial page load (before the ajax call renders the partial), jQuery won't see the $('#property_street_address_1') element (trust me - it didn't).

所以我们在 Rails 应用程序中有一个部分正在加载到页面中。这意味着 DOM 已经创建,如果我们在初始页面加载时调用上面的函数(在 ajax 调用呈现部分之前),jQuery 将看不到 $('#property_street_address_1') 元素(相信我 - 它没有) t)。

So we need to delay the google.maps.places.Autocomplete() until after the element is present on the page.

所以我们需要延迟 google.maps.places.Autocomplete() 直到元素出现在页面上。

We can do this via the Ajax callback on successful load of the partial:

我们可以通过成功加载部分的 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

So here, essentially, we're doing the same thing as calling foo()

所以在这里,本质上,我们正在做与调用 foo() 相同的事情

回答by AngusC

No, you can't define a function in coffee script and have it generate a function declaration in coffee script

不,您不能在咖啡脚本中定义函数并让它在咖啡脚本中生成函数声明

Even if you just write

哪怕只是写

-> 123

the generated JS will be wrapped in parens, thus making it a function expression

生成的 JS 将被包裹在括号中,从而使其成为一个函数表达式

(function() {
  return 123;
});

My guess is that this is because function declarations get "hoisted" to the top of the enclosing scope which would break up the logical flow of the coffeescript source.

我的猜测是,这是因为函数声明被“提升”到封闭范围的顶部,这会破坏咖啡脚本源的逻辑流程。

回答by shaunc

Try this:

尝试这个:

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

Now the following will print "true":

现在以下将打印“true”:

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

I don't actually use this, but do sometimes wish coffee functions had names for introspection.

我实际上并没有使用它,但有时确实希望咖啡函数具有用于内省的名称。