我看到了这种模式:
Money = (function() {
function Money(rawString) {
this.cents = this.parseCents(rawString);
}
});
在此CoffeeScript screencast preview中。 (截屏视频的主页为here。)
现在,我不明白这种模式。有Money
函数包含Money
函数。那是什么意思?
有人可以解释一下吗?
答案 0 :(得分:17)
正如引用的那样,除了可以从Money
对象中删除外window
符号之外没有任何意义(IE7及以下除外,但这是另一个故事),因为它是正常的(隐式)window
的属性(与var
或从函数声明派生的符号相对)。但即使这样,外部Money
符号也会收到一个绝对无效的函数。它会被错误引用吗?
例如,这是一个相当标准的模式:
Money = (function() {
var someCompletelyPrivateVariable;
function doSomethingCompletelyPrivate() {
}
function Money(rawString) {
this.cents = this.parseCents(rawString);
}
return Money;
})();
这是模块模式,它允许您拥有完全私有的变量和函数(两者都有图示),同时只有一个公共符号。但是我必须编辑一下才能创建它(最重要的编辑结尾是return Money;
,并且在匿名函数之后添加()
所以我们调用< / em>它而不仅仅是定义它。
答案 1 :(得分:15)
使用视频声称的CoffeeScript代码是正确的转换......
class Money
constructor: (rawString) ->
@cents = @parseCents rawString
... CoffeeScript将生成以下内容,与@ T.J基本相同。克劳德的回答:
var Money;
Money = (function() {
function Money(rawString) {
this.cents = this.parseCents(rawString);
}
return Money;
})();
我只是发布这个来展示CoffeeScript 实际上做了什么,而且视频并不代表现实。
如果您visit the site,则可以看到转化,然后点击“试用CoffeeScript”按钮。
请不“接受”这个答案。
修改强>
要添加一些使用范围的私有变量用法,您可以这样做:
class Money
priv=0
constructor: (rawString) ->
@cents = @parseCents rawString
@id = priv++
...呈现为:
var Money;
Money = (function() {
var priv;
priv = 0;
function Money(rawString) {
this.cents = this.parseCents(rawString);
this.id = priv++;
}
return Money;
})();
顺便说一句,我对CoffeeScript一无所知。它的语法让我感到困惑,但也许只是因为我不习惯它。
我喜欢JavaScript的方式(特别是新的和未来的变化)。
答案 2 :(得分:4)
我是所提到的截屏视频的作者,以及该片段的来源。一些澄清:
我会在上面提到的视频和预览中添加说明。
否则,Stack Overflow上的其他解释是正确的。如果您正在构建JavaScript类,则应返回当前对象并调用上面显示的匿名函数。但这不是CoffeeScript的重点。 ; - )
答案 3 :(得分:2)
它看起来不是一个真实的例子,“外部”功能的分组操作符是没有意义的,正如TJ所说,它绝对没有任何作用。被称为构造函数,它将返回一个空对象。
@TJ - 报价是正确的,您需要观看大约40秒的视频。
答案 4 :(得分:2)
Money = (function() {
var uid = 0;
function Money(rawString) {
this.cents = this.parseCents(rawString);
this.uid = uid++;
}
return Money;
})();
这种模式的另一个用例是让局部变量就像静态绑定到函数一样。
这与模块模式略有不同,因为您将静态私有信息添加到函数中。而不是打包数据并返回一个在范围内有一些局部变量的对象。
实现这一目标的另一个选择是使用Money.uid
,但这将是公开的。
答案 5 :(得分:1)
这里有三件事:
首先,正如其他回答者所指出的那样,在PeepCode截屏视频中给出并在问题中引用的代码有两个错误。有return
,外部函数被调用。
其次,作为T.J.注意,这是一个模块模式。您可以在CoffeeScript class
块中执行任意代码,并且变量遵循与其他函数相同的作用域规则。所以,例如,你可以写
class HashedPassword
salt = Math.random()
constructor: (password) ->
@value = hash password, salt
在这种情况下,salt
仅在HashedPassword
类定义中可见。
最后,应该注意的是,这是CoffeeScript唯一使用“命名”函数的地方(那些用function foo()
而不是foo = function()
声明的函数)。命名函数非常适合堆栈跟踪等,但它们会导致IE(&lt; 9)和其他浏览器之间出现不一致,除非作用于这样的模块(参见CoffeeScript FAQ,标题为“是”有没有办法命名函数,用于反射和递归?“)。因此,class
语法的二次使用是安全地声明命名函数。
我希望能回答你的问题,Šime。
答案 6 :(得分:0)
外部Money函数不带参数。内部Money函数通过闭包捕获rawString。这里的优点是您不会使用内部Money函数定义来污染全局命名空间。
编辑:我同意TJ的说法,现在的模式是无用的。它没有做任何事情,外部功能仅用于范围界定。在没有看到截屏作者的完整示例的情况下,很难分辨出他的目标。