如何在CoffeeScript中定义全局变量?

时间:2010-11-18 12:29:16

标签: javascript coffeescript

在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中定义全局变量。 “将它们作为窗口上的属性附加”是什么意思?

8 个答案:

答案 0 :(得分:418)

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

因此,由于没有办法从咖啡脚本方面将某些东西“泄漏”到全局命名空间,故你需要将全局变量定义为的属性全球对象

  

将它们作为属性附加到窗口

这意味着您需要执行处理浏览器案例的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;

首先它将检查是否定义了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.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

答案 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)

添加到Ivo Wetzel's answer

我似乎只能在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

这很有效,因为在调用ReferenceFunction'裸'时(即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