这个 JavaScript 模式是怎么回事?

发布于 2024-11-07 15:25:46 字数 445 浏览 0 评论 0原文

我看到了这种模式:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

暖树树初阳… 2024-11-14 15:25:46

正如所引用的,除了可以从 window 对象中删除外部 Money 符号(IE7 及更低版本除外,但那是另一个故事)之外,该模式没有任何意义,因为它是 window 的普通(隐式)属性(与 var 或从函数声明派生的符号相反)。但即便如此,外部的 Money 符号接收的函数绝对不执行任何操作。会不会被错误引用?

例如,这是一种相当标准的模式:

Money = (function() {
    var someCompletelyPrivateVariable;

    function doSomethingCompletelyPrivate() {
    }

    function Money(rawString) {
        this.cents = this.parseCents(rawString);
    }

    return Money;
})();

这就是模块模式,它允许您拥有完全私有的变量和函数(均已说明),同时只有一个公共符号。但我必须进行相当多的编辑才能创建它(最重要的编辑是末尾的 return Money; 以及在匿名函数之后添加 ()所以我们调用它而不是仅仅定义它。

As quoted, there's no point to that pattern other than that the outer Money symbol can be deleted from the window object (except on IE7 and below, but that's another story) because it's a normal (implicit) property of window (as opposed to a var or a symbol deriving from a function declaration). But even then, the outer Money symbol receives a function that does absolutely nothing. Could it be misquoted?

For instance, here's a fairly standard patttern:

Money = (function() {
    var someCompletelyPrivateVariable;

    function doSomethingCompletelyPrivate() {
    }

    function Money(rawString) {
        this.cents = this.parseCents(rawString);
    }

    return Money;
})();

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.

旧时浪漫 2024-11-14 15:25:46

使用视频声称的 CoffeeScript 代码是正确的转换...

class Money
    constructor: (rawString) ->
        @cents = @parseCents rawString

...CoffeeScript 将生成以下内容,这与 @TJ Crowder 的答案基本相同:

var Money;
Money = (function() {
  function Money(rawString) {
    this.cents = this.parseCents(rawString);
  }
  return Money;
})();

我只是发布此内容以显示 CoffeeScript 实际上 确实如此,并且视频并不代表现实。

如果您访问该网站并点击“尝试 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 的本来面目(尤其是新的和即将到来的变化)。

Using the CoffeeScript code that the video claims is a proper conversion...

class Money
    constructor: (rawString) ->
        @cents = @parseCents rawString

...CoffeeScript will generate the following, which is basically identical to @T.J. Crowder's answer:

var Money;
Money = (function() {
  function Money(rawString) {
    this.cents = this.parseCents(rawString);
  }
  return Money;
})();

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:

class Money
    priv=0
    constructor: (rawString) ->
        @cents = @parseCents rawString
        @id = priv++

...which renders as:

var Money;
Money = (function() {
  var priv;
  priv = 0;
  function Money(rawString) {
    this.cents = this.parseCents(rawString);
    this.id = priv++;
  }
  return Money;
})();

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).

永不分离 2024-11-14 15:25:46

我是上述截屏视频的作者,也是该片段的来源。一些说明:

  • 提到该代码片段的上下文是 JavaScript 和 CoffeeScript 语法的动画比较。
  • 它被有意简化,以免在视频中正在教授的 CoffeeScript 概念的上下文中增加额外的混乱(该视频并没有试图教授 JavaScript 构造函数或类语法)。
  • 您可以通过通过 CoffeeScript 编译器运行任何 CoffeeScript 片段的完整 JavaScript 文本(如截屏视频中所示),或者在官方 CoffeeScript 网站上运行它。

我将对上述视频和预览添加说明。

否则,Stack Overflow 上的其他解释是正确的。如果您正在构建 JavaScript 类,您应该返回当前对象并调用上面显示的匿名函数。但这不是 CoffeeScript 的重点。 ;-)

I'm the author of the screencast mentioned, and the source of the snippet. A few clarifications:

  • The context in which the snippet was mentioned was in an animated comparison of JavaScript and CoffeeScript syntax.
  • It was intentionally simplified so as to not add extra confusion in the context of the CoffeeScript concept being taught at that exact moment in the video (the video was not trying to teach JavaScript constructor or class syntax).
  • You can get the full JavaScript text of any CoffeeScript snippet by running it through the CoffeeScript compiler as shown in the screencast, or by running it on the official CoffeeScript website.

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. ;-)

橪书 2024-11-14 15:25:46

它看起来不像一个真实的例子,“外部”函数的分组运算符毫无意义,正如 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.

忆伤 2024-11-14 15:25:46
Money = (function() {
    var uid = 0;
    function Money(rawString) {
        this.cents = this.parseCents(rawString);
        this.uid = uid++;
    }
    return Money;
})();

此模式的另一个用例是让局部变量的行为就像静态绑定到函数一样。

这与模块模式略有不同,因为您向函数添加静态私有信息。而不是打包数据并返回范围内具有一些局部变量的对象。

实现此目的的另一个选项是使用 Money.uid,但这将是公开的。

Money = (function() {
    var uid = 0;
    function Money(rawString) {
        this.cents = this.parseCents(rawString);
        this.uid = uid++;
    }
    return Money;
})();

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.

妞丶爷亲个 2024-11-14 15:25:46

这里发生了三件事:

首先,正如其他回答者所指出的,PeepCode 截屏视频中给出并在问题中引用的代码有一些错误。有一个返回,并且调用外部函数。

其次,正如 TJ 指出的,这是一个模块模式。您可以在 CoffeeScript class 块中执行任意代码,并且变量遵循与其他函数中相同的作用域规则。因此,例如,您可以编写

class HashedPassword
  salt = Math.random()
  constructor: (password) ->
    @value = hash password, salt

在这种情况下 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 write

class HashedPassword
  salt = Math.random()
  constructor: (password) ->
    @value = hash password, salt

in which case salt is visible only within the HashedPassword 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 than foo = 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 the class syntax is to safely declare named functions.

I hope that answers your question, Šime.

山人契 2024-11-14 15:25:46

外部 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文