在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。“将它们作为属性附加到窗口”是什么意思?
由于coffee脚本没有var语句,它会自动为coffee-script中的所有变量插入var语句,这样可以防止编译后的JavaScript版本将所有内容泄露到全局名称空间。
因此,由于无法有意地将某些内容从coffee-script方面“泄漏”到全局名称空间,因此需要将全局变量定义为全局对象的属性。
将它们作为属性附加到窗口上
这意味着你需要做一些类似window的事情。Foo = 'baz';,它处理浏览器的情况,因为那里的全局对象是窗口。
node . js
在Node.js中没有窗口对象,相反,有一个exports对象,它被传递到包装Node.js模块的包装器中(参见:https://github.com/ry/node/blob/master/src/node.js#L321),所以在Node.js中,你需要做的是导出。Foo = 'baz';
现在让我们看看你从文件中引用的内容:
...同时针对CommonJS和浏览器:root = exports ?这
这显然是一个coffee-script,所以让我们来看看它实际上编译成什么:
var root;
root = (typeof exports !== "undefined" && exports !== null) ? exports : this;
首先,它将检查是否定义了exports,因为试图引用JavaScript中不存在的变量会产生SyntaxError(与typeof一起使用时除外)
因此,如果存在exports,在Node.js中(或者在一个写得不好的网站中……)根将指向exports,否则指向this。这是什么?
(function() {...}).call(this);
在函数上使用.call会将函数中的this绑定到传递的第一个参数,对于浏览器来说,它现在是窗口对象,对于Node.js来说,它将是全局上下文,也可以作为全局对象。
但是因为你在Node.js中有require函数,所以不需要给Node.js中的全局对象赋值,相反,你可以给exports对象赋值,然后由require函数返回。
Coffee-Script
说了这么多,下面是你需要做的:
root = exports ? this
root.foo = -> 'Hello World'
这将在全局命名空间中声明函数foo(不管它是什么)。
这就是全部:)
对我来说,@atomicules似乎有最简单的答案,但我认为它可以再简化一点。你需要在任何你想要全局的东西前面加上@,这样它就会编译成这个。任何东西,this指向全局对象。
所以…
@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
由于coffee脚本没有var语句,它会自动为coffee-script中的所有变量插入var语句,这样可以防止编译后的JavaScript版本将所有内容泄露到全局名称空间。
因此,由于无法有意地将某些内容从coffee-script方面“泄漏”到全局名称空间,因此需要将全局变量定义为全局对象的属性。
将它们作为属性附加到窗口上
这意味着你需要做一些类似window的事情。Foo = 'baz';,它处理浏览器的情况,因为那里的全局对象是窗口。
node . js
在Node.js中没有窗口对象,相反,有一个exports对象,它被传递到包装Node.js模块的包装器中(参见:https://github.com/ry/node/blob/master/src/node.js#L321),所以在Node.js中,你需要做的是导出。Foo = 'baz';
现在让我们看看你从文件中引用的内容:
...同时针对CommonJS和浏览器:root = exports ?这
这显然是一个coffee-script,所以让我们来看看它实际上编译成什么:
var root;
root = (typeof exports !== "undefined" && exports !== null) ? exports : this;
首先,它将检查是否定义了exports,因为试图引用JavaScript中不存在的变量会产生SyntaxError(与typeof一起使用时除外)
因此,如果存在exports,在Node.js中(或者在一个写得不好的网站中……)根将指向exports,否则指向this。这是什么?
(function() {...}).call(this);
在函数上使用.call会将函数中的this绑定到传递的第一个参数,对于浏览器来说,它现在是窗口对象,对于Node.js来说,它将是全局上下文,也可以作为全局对象。
但是因为你在Node.js中有require函数,所以不需要给Node.js中的全局对象赋值,相反,你可以给exports对象赋值,然后由require函数返回。
Coffee-Script
说了这么多,下面是你需要做的:
root = exports ? this
root.foo = -> 'Hello World'
这将在全局命名空间中声明函数foo(不管它是什么)。
这就是全部:)
Ivo很好地解决了这个问题,但我要提到一个你可以使用的小技巧,尽管如果你追求的是风格点,我不建议你这么做:你可以通过反勾转义直接将JavaScript代码嵌入到CoffeeScript中。
然而,这通常是一个坏主意:CoffeeScript编译器不知道这些变量,这意味着它们不会遵守正常的CoffeeScript作用域规则。所以,
`foo = 'bar'`
foo = 'something else'
编译,
foo = 'bar';
var foo = 'something else';
现在你有两个傻子在不同的范围内。正如Ivy所描述的,如果不引用全局对象,就无法从CoffeeScript代码中修改全局foo。
当然,这只是当你在coffeescript中赋值给foo时才会出现问题——如果foo在被赋予初始值后变成只读的(即它是一个全局常量),那么嵌入式JavaScript解决方案可能是可以接受的(尽管仍然不推荐)。