这个 JavaScript 模式是怎么回事?
我看到了这种模式:
Money = (function() {
function Money(rawString) {
this.cents = this.parseCents(rawString);
}
});
在此 CoffeeScript 截屏预览中。 (截屏视频的主页位于此处。)
现在,我不明白这种模式。有一个 Money
函数包含一个 Money
函数。那是关于什么的?
有人可以解释一下吗?
I saw this pattern:
Money = (function() {
function Money(rawString) {
this.cents = this.parseCents(rawString);
}
});
in this CoffeeScript screencast preview. (The homepage for the screencast is here.)
Now, I don't understand this pattern. There is a Money
function that contains a Money
function. What's that about?
Could someone explain?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
正如所引用的,除了可以从
window
对象中删除外部Money
符号(IE7 及更低版本除外,但那是另一个故事)之外,该模式没有任何意义,因为它是window
的普通(隐式)属性(与var
或从函数声明派生的符号相反)。但即便如此,外部的 Money 符号接收的函数绝对不执行任何操作。会不会被错误引用?例如,这是一种相当标准的模式:
这就是模块模式,它允许您拥有完全私有的变量和函数(均已说明),同时只有一个公共符号。但我必须进行相当多的编辑才能创建它(最重要的编辑是末尾的
return Money;
以及在匿名函数之后添加()
所以我们调用它而不是仅仅定义它。As quoted, there's no point to that pattern other than that the outer
Money
symbol can be deleted from thewindow
object (except on IE7 and below, but that's another story) because it's a normal (implicit) property ofwindow
(as opposed to avar
or a symbol deriving from a function declaration). But even then, the outerMoney
symbol receives a function that does absolutely nothing. Could it be misquoted?For instance, here's a fairly standard patttern:
That's the module pattern, and it lets you have completely private variables and functions (both illustrated) whilst only having one public symbol. But I've had to edit a fair bit to create that (the most significant edits being the
return Money;
at the end and the addition of()
after the anonymous function so we're calling it rather than just defining it.使用视频声称的 CoffeeScript 代码是正确的转换...
...CoffeeScript 将生成以下内容,这与 @TJ Crowder 的答案基本相同:
我只是发布此内容以显示 CoffeeScript 实际上 确实如此,并且视频并不代表现实。
如果您访问该网站并点击“尝试 CoffeeScript”按钮,您就可以看到转换结果。
请不要“接受”这个答案。
编辑:
要添加一些利用作用域的私有变量用法,您可以这样做:
...呈现为:
顺便说一句,我对 CoffeeScript 一无所知。它的语法对我来说看起来很混乱,但也许只是因为我不习惯它。
我喜欢 JavaScript 的本来面目(尤其是新的和即将到来的变化)。
Using the CoffeeScript code that the video claims is a proper conversion...
...CoffeeScript will generate the following, which is basically identical to @T.J. Crowder's answer:
I'm just posting this to show what CoffeeScript actually does, and that the video does not represent the reality.
You can see the conversion if you visit the site and click the "Try CoffeeScript" button.
Please do not "accept" this answer.
EDIT:
To add some private variable usage that utilizes the scope, you could do this:
...which renders as:
By the way, I know nothing about CoffeeScript. Its syntax looks confusing to me, but perhaps just because I'm not accustomed to it.
I like JavaScript the way it is (especially with the new and yet to come changes).
我是上述截屏视频的作者,也是该片段的来源。一些说明:
我将对上述视频和预览添加说明。
否则,Stack Overflow 上的其他解释是正确的。如果您正在构建 JavaScript 类,您应该返回当前对象并调用上面显示的匿名函数。但这不是 CoffeeScript 的重点。 ;-)
I'm the author of the screencast mentioned, and the source of the snippet. A few clarifications:
I'll add a clarification to the video and preview mentioned above.
Otherwise, the other explanations here on Stack Overflow are correct. If you're building a JavaScript class you should return the current object and call the anonymous function shown above. But that's not the point of CoffeeScript. ;-)
它看起来不像一个真实的例子,“外部”函数的分组运算符毫无意义,正如 TJ 所说,它绝对没有任何作用。作为构造函数调用,它将返回一个空对象。
@TJ - 引用是正确的,您需要观看大约 40 秒的视频。
It doesn't look like a real example, the grouping operator of the "outer" function is pointless and as TJ says, it does absolutely nothing. Called as a constructor, it will return an empty object.
@TJ - the quote is correct, you need to watch about 40 seconds of the video.
此模式的另一个用例是让局部变量的行为就像静态绑定到函数一样。
这与模块模式略有不同,因为您向函数添加静态私有信息。而不是打包数据并返回范围内具有一些局部变量的对象。
实现此目的的另一个选项是使用 Money.uid,但这将是公开的。
Another use case of this pattern is to have local variables that act as if there statically bound to the function.
This is subtly different from the module pattern because your adding static private information to a function. Instead of packaging data and returning an object which has some local variables in scope.
The other option for achieving this would be using
Money.uid
but that would be public.这里发生了三件事:
首先,正如其他回答者所指出的,PeepCode 截屏视频中给出并在问题中引用的代码有一些错误。有一个
返回
,并且调用外部函数。其次,正如 TJ 指出的,这是一个模块模式。您可以在 CoffeeScript
class
块中执行任意代码,并且变量遵循与其他函数中相同的作用域规则。因此,例如,您可以编写在这种情况下
salt
仅在HashedPassword
类定义中可见。最后,应该指出的是,这是 CoffeeScript 唯一使用“命名”函数的地方(那些用
function foo()
声明的函数,而不是foo = function()
声明的函数) 。命名函数对于堆栈跟踪等非常有用,但它们会导致 IE (< 9) 和其他浏览器之间的不一致除非在这样的模块中(请参阅 CoffeeScript 常见问题,标题“有没有办法命名函数,用于反射和递归?”)。因此,class
语法的第二个用途是安全地声明命名函数。我希望这能回答你的问题,西梅。
There are three things going on here:
First, as other answerers have noted, the code given in the PeepCode screencast and cited in the question has a couple of mistakes. There is a
return
, and the outer function is called.Second, as T.J. noted, this is a module pattern. You can execute arbitrary code in CoffeeScript
class
blocks, and variables obey the same scoping rules as in other functions. So, for instance, you could writein which case
salt
is visible only within theHashedPassword
class definition.Finally, it should be noted that this is the only place that CoffeeScript ever uses "named" functions (those declared with
function foo()
rather thanfoo = function()
). Named functions are great for stack traces and such, but they cause inconsistencies between IE (< 9) and other browsers unless scoped in a module like this (see the CoffeeScript FAQ, heading "Is there any way to name functions, for reflection and recursion?"). So a secondary use of theclass
syntax is to safely declare named functions.I hope that answers your question, Šime.
外部 Money 函数不带任何参数。内部 Money 函数通过闭包捕获 rawString。这里的优点是您不会用内部 Money 函数定义污染全局命名空间。
编辑:我同意 TJ 的观点,即目前的模式是无用的。它不执行任何操作,外部函数仅用于确定作用域。如果没有看到截屏视频作者的完整示例,很难判断他的意图。
The outer Money function takes no arguments. The inner Money function captures rawString via closure. The advantage here is that you're not polluting the global namespace with the inner Money function definition.
EDIT: I would agree with TJ that the pattern as it stands is useless. It doesn't do anything and the outer function is used solely for scoping. Without seeing the screencast author's complete example, it's hard to tell where he is going with this.