CoffeeScript和命名函数


10

在其他地方,关于CoffeeScript中命名函数的术语引起了争论。特别是有人提到这样的事情:

 foo = ->
    console.log("bar")

作为命名函数。但是,它的反对意见是CoffeeScript中的所有内容都是匿名函数,并且没有命名函数。确实是这样,CoffeeScript仅具有函数表达式,然后可以将其存储在变量中。但我认为这并不意味着将其称为命名函数是错误的。

如我所见,它是一个命名函数,因为它已被命名。没错,它不是一个命名函数,就像其他语言中的命名函数一样,但是我认为它足够接近以至于不宜将其称为命名函数。坚持认为否则似乎只是挑剔。

我是否在吃午餐,以为坚持认为这不是命名函数只是挑剔?


3
这整个问题不是很好吗?:-)
Mat

@Mat,是的,看来我无法避免挑剔
Winston Ewert 2013年

对于与我交谈的少量程序员(即在SE.SE之外),他们通常会说使用JavaScript的命名函数作为“类”(构造函数),而匿名函数存储在变量中,用于普通的旧函数。
2013年

1
“挑剔”意味着答案并不重要,理解语言的微妙之处并不是一个值得的目标。
2013年

我可以像CoffeeScript那样看待它:foo = ->只是一个普通的旧函数,class Foo而是一个构造函数。我认为没有理由foo = ->将其严格称为匿名。
2013年

Answers:


20

CoffeeScript与JavaScript紧密相关,并且JavaScript区分以下表达式:

function foo() { ... }
var foo = function () { ... }

实际上,您甚至可以编写:

var foo = function bar () { ... }

由于这种差异在JavaScript中很重要,因此在谈论CoffeeScript时使用相同的术语是有意义的。但是,CoffeeScript不支持类似function foo ()语法的任何内容,因此我们可以说它不具有“命名”功能。

从某种意义上说,名称是中的函数定义的一部分function foo() { ... },在其他情况下,您只需创建一个函数并将其分配给变量即可。例如,这体现在name函数的(非标准)属性中:第一种情况foo.name会给您"foo",第二种情况会给您""

此外,在JavaScript中,它们在引入范围上的方式也有所不同:第一个版本是“悬挂式”的,并且在整个范围内都可用,而第二个定义仅在分配后才可用。

基本上,只需将其视为特定于JavaScript的行话即可,因为CoffeeScript与JS紧密相关,因此可以将其转移到CoffeeScript。


1
的确没有这样的东西function foo () {}。但是,您仍然可以通过class构造初始化命名函数。只是编译后的CoffeeScript(生成的JavaScript)比大多数编写命名函数的方式更为冗长。
2013年

1
同时,还有一个技术警告:foo功能的身体不会被吊起。
2013年

1
耶利夫斯:没问题。我对您的答案写的最后一条评论的一个更正:您class foo的功能主体不会被提升到文件的顶部。
2013年

由于CoffeeScript没有区分命名函数和匿名函数,因此我们真的可以说该术语已转移到CoffeeScript吗?Java语言的区别在该语言中根本没有任何意义。
Winston Ewert 2013年

@WinstonEwert:这很重要,因为CoffeeScript 非常接近 JavaScript。毕竟,“黄金法则”是:“这只是JavaScript”
Tikhon Jelvis

5

值得注意的是,用户明确声明他们正在将“匿名函数转换为命名函数”,这两个术语在JavaScript世界中都具有很强的现有含义以及明显不同的功能。鉴于现有含义,他们没有做任何事情,我指出了这一点。

CoffeeScript尚未从JavaScript中移除,您应该重新定义它们共同使用的术语,以一种语言表达其他含义。CoffeeScript并不存在,它可能以您认为C ++与Assembly分离的方式从其JavaScript实现中删除。知道匿名函数和命名函数之间的区别很重要,因为如果您希望“命名” CoffeeScript函数的行为类似于实际的命名函数,那么您将很失望:

doStuff() # I cause an error

# ... later

doStuff = (x,y) ->
  alert("Were I actually a named function, this would work!")

等效的JavaScript可以正常工作,并带有真实的命名函数:

doStuff(); // I work just fine!

// later....

function doStuff() {
  alert("I'm a real named function!")
}

你可能是对的,我只是在“挑剔”,但是那又如何呢?在计算机中的微妙点编程的事情,并且是“技术上”正确是很重要的。编写能正常工作的代码与真正理解代码为什么正确之间的区别是。


1
例如,如果我在Python中尝试了您的示例,它仍然无法正常工作。因此,我不确定这与命名vs匿名函数有什么关系。
Winston Ewert

1
@WinstonEwert看到我的更新。Python确实与它没有任何关系……
user229044 2013年

@meager,我的意思是,尽管命名函数在Javascript中起作用,但它们不一定会那样操作。因此,提升本身不会使CoffeeScript的功能失去资格。
Winston Ewert 2013年

是的,您必须了解CoffeeScript中的所有函数都是匿名的(实际上,我更愿意说它们都是函数表达式)。但这并不意味着我们有时不能对术语有些松懈。这就是为什么我认为坚持不敢将它们称为命名函数的原因。
Winston Ewert 2013年

3

我是否在吃午餐,以为坚持认为这不是命名函数只是挑剔?

否。毕竟,就语义而言,您的函数引用存储在变量中,您可以通过变量来引用。


3

绝对不是nitpick,imo。我广泛使用它来提高可读性:

readfile()
dothis()
dothat()
thistoo()
writefile()

function readfile() {
    ...
}
...

从而:

“咖啡脚本”中的实名函数

hello()

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

您可以通过反引号`

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

干杯


1

不要浪费时间与学徒争论。它永远不会富有成果。是的,每个人都知道CoffeeScript中“命名函数”的含义,即使在技术上不正确。不可以,使用技术上不正确但广为人知的术语与所提出解决方案的正确性或不正确性无关。在不增加措辞尴尬的情况下,可能会更精确吗?可能不是。但是,这并不意味着人们会顺其自然。想象一下在对话另一端的那个家伙

从技术上讲,这是不正确的原因是因为您尚未命名该函数,而是已命名对该函数的引用。考虑:

foo = bar = ->
  console.log "What's my name?"

函数的名称是什么? foobar都引用相同的函数,但名称不同。此外,任一foobar可以在任何时候重新分配来引用一个不同的功能,或者甚至不同类型的完全,在不改变功能本身。


0

因此,我的阅读方式如下:

当您在JavaScript控制台中使用声明函数时

var foo = function() { ... }

然后在foo不带括号的情况下调用,它将返回

function() { ... }

但是,如果使用

function foo() { ... }

然后foo再次调用而不带括号,它将返回

function foo() { ... }

在第一种情况下,我想说的是声明一个名为“ foo”的变量,该变量中存储了一个匿名函数。在第二种情况下,我会说您实际上是在声明一个名为“ foo”的命名函数。

因为CoffeeScript使用第一种模式,所以我同意在技术上正确的是,CoffeeScript的函数都是存储在命名变量中的所有匿名函数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.