Harmen 的回答非常好,但让我详细说明一下 CoffeeScript 编译器在哪里执行此操作以及原因。
当你用coffee -c foo.coffee 编译某些东西时,你总是会得到一个看起来像这样的foo.js:
(function() {
...
}).call(this);
这是为什么呢?好吧,假设你把一个任务像
x = 'stringy string'
在foo.coffee。当它看到时,编译器会问:x 是否已经存在于这个作用域或外部作用域中?如果没有,它会在 JavaScript 输出中该范围的顶部放置一个 var x 声明。
现在假设你写
x = 42
在bar.coffee 中,编译两者,并将foo.js 与bar.js 连接以进行部署。你会得到
(function() {
var x;
x = 'stringy string';
...
}).call(this);
(function() {
var x;
x = 42;
...
}).call(this);
所以foo.coffee 中的x 和bar.coffee 中的x 完全相互隔离。这是 CoffeeScript 的一个重要部分:变量永远不会从一个 .coffee 文件泄漏到另一个文件,除非显式导出(通过附加到共享全局,或 Node.js 中的 exports)。 p>
您可以通过使用coffee 的-b(“bare”)标志来覆盖它,但这应该只在非常特殊的情况下使用。如果你在上面的例子中使用它,你会得到的输出是
var x;
x = 'stringy string';
...
var x;
x = 42;
...
这可能会产生可怕的后果。要自己测试,请尝试在foo.coffee 中添加setTimeout (-> alert x), 1。请注意,您不必自己连接这两个 JS 文件——如果您使用两个单独的 <script> 标记将它们包含在一个页面中,它们仍然可以作为一个文件有效地运行。
通过隔离不同模块的范围,CoffeeScript 编译器让您不必担心项目中的不同文件是否可能使用相同的局部变量名。这是 JavaScript 世界中的常见做法(例如,请参阅 jQuery source 或几乎任何 jQuery 插件)—CoffeeScript 会为您处理它。