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
Function declaration in CoffeeScript
提问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: class
definitions. 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.
我实际上并没有使用它,但有时确实希望咖啡函数具有用于内省的名称。