如何在CoffeeScript中定义全局variables?

在Coffeescript.org上:

bawbag = (x, y) -> z = (x * y) bawbag(5, 10) 

将编译为:

 var bawbag; bawbag = function(x, y) { var z; return (z = (x * y)); }; bawbag(5, 10); 

通过node.js下的咖啡脚本编译包装:

 (function() { var bawbag; bawbag = function(x, y) { var z; return (z = (x * y)); }; bawbag(5, 10); }).call(this); 

文档说:

如果您想为其他脚本创build顶级variables,请将它们作为窗口上的属性或CommonJS中的exports对象附加。 存在的操作符(如下所示)为您提供了一种可靠的方法来确定将它们添加到哪里,如果您同时针对CommonJS和浏览器:root = exports? 这个

如何在CoffeeScript中定义全局variables? “将它们附加为窗口上的属性”是什么意思?

由于咖啡脚本没有var语句,它会自动将其插入咖啡脚本中的所有variables,这样可以防止编译的JavaScript版本将所有内容泄漏到全局名称空间中

所以,因为没有办法让事情有意地从事物的咖啡脚本一侧“泄漏”到全局命名空间中 ,所以需要将全局variables定义为全局对象的属性。

将它们作为属性附加在窗口上

这意味着你需要做一些像window.foo = 'baz'; ,它处理浏览器的情况,因为那里的全局对象window

Node.js的

在Node.js中,没有window对象,而是将exports对象传递到封装了Node.js模块的封装器中(请参阅: https : //github.com/ry/node/blob/master/src/node。 js#L321 ),所以在Node.js中你需要做的是exports.foo = 'baz';

现在让我们来看看你在文档中引用的内容:

针对CommonJS和浏览器:root = exports? 这个

这显然是咖啡脚本,所以让我们来看看实际编译的内容:

 var root; root = (typeof exports !== "undefined" && exports !== null) ? exports : this; 

首先它将检查是否定义了输出,因为试图在JavaScript中引用一个不存在的variables会产生一个SyntaxError(除非它与typeof

所以如果exports存在,Node.js(或者在一个写得不好的Web站点中)的情况就是指向exports ,否则就是exports 。 那这是什么?

 (function() {...}).call(this); 

在一个函数上使用.call将把函数内部的这个函数绑定到传递的第一个参数,在浏览器的情况下this将成为window对象,在Node.js的情况下,它将成为全局上下文global对象。

但是由于Node.js中有require函数,因此不需要为Node.js中的global对象分配内容,而是分配给exports对象,然后由require函数返回。

咖啡脚本

在所有的解释之后,你需要做的是:

 root = exports ? this root.foo = -> 'Hello World' 

这将在全局命名空间中声明我们的函数foo (无论发生什么)。
就这样 :)

对我来说,似乎@atomicules有最简单的答案,但我认为它可以简化多一点。 你需要在任何你想成为全局的东西之前放一个@ ,这样它就可以编译成this this.anythingthis就是全局对象。

所以…

 @bawbag = (x, y) -> z = (x * y) bawbag(5, 10) 

编译成…

 this.bawbag = function(x, y) { var z; return z = x * y; }; bawbag(5, 10); 

并且在由node.js给出的包装内部和外部工作

 (function() { this.bawbag = function(x, y) { var z; return z = x * y; }; console.log(bawbag(5,13)) // works here }).call(this); console.log(bawbag(5,11)) // works here 

Ivo钉了它,但我会提到,有一个肮脏的技巧,你可以使用,但我不build议,如果你要风格点:你可以embeddedJavaScript代码直接在你的CoffeeScript中用反引号逃脱它。

然而,这是为什么这通常是一个坏主意:CoffeeScript编译器不知道这些variables,这意味着他们不会遵守正常的CoffeeScript范围规则。 所以,

 `foo = 'bar'` foo = 'something else' 

编译

 foo = 'bar'; var foo = 'something else'; 

现在你已经有了两个不同的范围。 像Ivy所描述的那样,没有办法从CoffeeScript代码中修改全局 foo而不引用全局对象。

当然,如果您在CoffeeScript中为foo赋值,这只是一个问题 – 如果foo在被赋予其初始值(即,它是一个全局常量)后变为只读,那么embedded式JavaScript解决scheme可能有点令人满意(虽然仍然不推荐)。

当您通过node.js下的coffee-script编译代码时,您可以传递-b选项。 编译后的代码将和coffeescript.org一样。

添加到Ivo Wetzel的答案

似乎有一个简短的exports ? this语法exports ? this exports ? this只能在Google群组发帖中findlogging/提及。

也就是说,在一个网页中使全局可用的函数,你再次用@前缀声明该函数:

 <script type="text/coffeescript"> @aglobalfunction = aglobalfunction = () -> alert "Hello!" </script> <a href="javascript:aglobalfunction()" >Click me!</a> 

我认为你所要达到的目标可以简单地做到这一点:

在编译咖啡脚本时,使用“-b”参数。

-b / --bare 编译没有顶级函数安全包装器的JavaScript。

所以像这样: coffee -b --compile somefile.coffee whatever.js

这将输出您的代码就像在CoffeeScript.org网站。

如果你是一个坏人(我是一个坏人),你可以像这样简单:( (->@)()

如在,

 (->@)().im_a_terrible_programmer = yes console.log im_a_terrible_programmer 

这是有效的,因为当调用Reference Function '裸'(即func()而不是new func()obj.func() )时,通常被称为“函数调用调用模式” 总是将其绑定到该执行上下文的全局对象。

上面的CoffeeScript简单地编译为(function(){ return this })() ; 所以我们正在行使这种行为来可靠地访问全局对象。

由于coffeescript本身很less使用,所以可以使用node.js或browserify提供的globalvariables(以及任何后代,如coffeeify,gulp构build脚本等)。

在node.js中global是全局名称空间。

在browserify global等于window

所以,只是:

 somefunc = -> global.variable = 123