在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下的coffee-script编译包装:
(function() {
var bawbag;
bawbag = function(x, y) {
var z;
return (z = (x * y));
};
bawbag(5, 10);
}).call(this);
文档说:
如果您想为其他脚本创建顶级变量, 将它们作为属性附加到窗口或导出对象中 CommonJS的。存在主义运算符(如下所述)给你一个 如果您同时定位两者,可以通过可靠的方法找出添加位置 CommonJS和浏览器:root = exports?此
如何在CoffeeScript中定义全局变量。 “将它们作为窗口上的属性附加”是什么意思?
答案 0 :(得分:418)
由于咖啡脚本没有var
语句,它会自动为咖啡脚本中的所有变量插入它,这样就可以防止已编译的JavaScript版本将所有内容泄漏到全局命名空间中。
因此,由于没有办法从咖啡脚本方面将某些东西“泄漏”到全局命名空间,故你需要将全局变量定义为的属性全球对象。
将它们作为属性附加到窗口
这意味着您需要执行处理浏览器案例的window.foo = 'baz';
之类的操作,因为全局对象是window
。
在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;
首先它将检查是否定义了exports
,因为尝试在JavaScript中引用不存在的变量否则会产生SyntaxError(除非它与typeof
一起使用)
因此,如果exports
存在,Node.js中的情况(或编写错误的WebSite ...)根将指向exports
,否则指向this
。那是什么this
?
(function() {...}).call(this);
在函数上使用.call
会将函数内的this
绑定到传递的第一个参数,以防浏览器this
现在成为window
对象,在Node.js的情况下,它将是全局上下文,它也可用作global
对象。
但是由于你在Node.js中有require
函数,所以不需要为Node.js中的global
对象赋值,而是分配给exports
对象。然后由require
函数返回。
完成所有解释后,您需要做的就是:
root = exports ? this
root.foo = -> 'Hello World'
这将在全局命名空间中声明我们的函数foo
(无论发生什么)
这就是全部:))
答案 1 :(得分:57)
对我而言,似乎@atomicules有最简单的答案,但我认为它可以简化一点。您需要在要成为全局的任何内容之前放置@
,以便它编译为this.anything
,this
引用全局对象。
@bawbag = (x, y) ->
z = (x * y)
bawbag(5, 10)
this.bawbag = function(x, y) {
var z;
return z = x * y;
};
bawbag(5, 10);
(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
答案 2 :(得分:33)
Ivo钉了它,但我会提到你可以使用一个肮脏的技巧,但是如果你想要使用样式点我不推荐它:你可以通过转义它直接在你的CoffeeScript中嵌入JavaScript代码用反叛。
然而,这就是为什么这通常是一个坏主意:CoffeeScript编译器不知道这些变量,这意味着他们不会遵守正常的CoffeeScript范围规则。所以,
`foo = 'bar'`
foo = 'something else'
编译到
foo = 'bar';
var foo = 'something else';
现在你已经在不同的范围内拥有两个foo
。正如Ivy所描述的那样,无法在不引用全局对象的情况下修改CoffeeScript代码中的全局 foo
。
当然,如果你在CoffeeScript中对foo
进行赋值,这只是一个问题 - 如果foo
在给定其初始值后变为只读(即它是一个全局常量),那么嵌入式JavaScript解决方案方法可能有点可接受(尽管仍然不推荐)。
答案 3 :(得分:11)
通过node.js下的coffee-script编译代码时,可以传递-b选项。 编译后的代码与coffeescript.org上的相同。
答案 4 :(得分:9)
我似乎只能在Google group posting上找到记录/提及的exports ? this
的简写语法。
即。在网页中,为了使全局可用的功能,您可以使用@
前缀再次声明该功能:
<script type="text/coffeescript">
@aglobalfunction = aglobalfunction = () ->
alert "Hello!"
</script>
<a href="javascript:aglobalfunction()" >Click me!</a>
答案 5 :(得分:9)
我认为你想要实现的目标可以简单地完成:
在编辑coffeescript时,请使用“-b”参数。
-b
/ --bare
在没有顶级功能安全包装的情况下编译JavaScript。
这样的事情:coffee -b --compile somefile.coffee whatever.js
这将输出您的代码,就像在CoffeeScript.org网站中一样。
答案 6 :(得分:6)
如果你是一个坏人(我是个坏人),你可以这么简单:(->@)()
如同,
(->@)().im_a_terrible_programmer = yes
console.log im_a_terrible_programmer
这很有效,因为在调用Reference
到Function
'裸'时(即func()
,而不是new func()
或obj.func()
),通常被称为“函数调用调用模式”的东西,总是将this
绑定到execution context的全局对象。
上面的CoffeeScript只编译为(function(){ return this })()
;所以我们正在行使这种行为来可靠地访问全局对象。
答案 7 :(得分:3)
由于coffeescript很少用于它自己,你可以使用node.js或browserify提供的global
变量(以及任何后代,如coffeeify,gulp构建脚本等)。
在node.js global
中是全局命名空间。
在浏览器中,global
等于window
。
所以,只是:
somefunc = ->
global.variable = 123