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

时间:2021-03-27 23:23:42

On Coffeescript.org:

在Coffeescript.org上:

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

bawbag(5, 10) 

would compile to:

将编译:

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

compiling via coffee-script under node.js wraps that so:

通过节点下的咖啡吧脚本进行编译。js包装,所以:

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

Docs say:

医生说:

If you'd like to create top-level variables for other scripts to use, attach them as properties on window, or on the exports object in CommonJS. The existential operator (covered below), gives you a reliable way to figure out where to add them, if you're targeting both CommonJS and the browser: root = exports ? this

如果您希望为其他脚本创建*变量,请将它们作为属性附加到窗口或CommonJS中的export对象上。存在操作符(如下所示)为您提供了一种可靠的方法来确定在何处添加它们,如果您同时针对CommonJS和浏览器:root = exports ?这

How do I define Global Variables then in CoffeeScript. What does 'attach them as properties on window' mean?

如何在CoffeeScript中定义全局变量。“将它们作为属性附加到窗口”是什么意思?

8 个解决方案

#1


416  

Since coffee script has no var statement it automatically inserts it for all variables in the coffee-script, that way it prevents the compiled JavaScript version from leaking everything into the global namespace.

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

So since there's no way to make something "leak" into the global namespace from the coffee-script side of things on purpose, you need to define your global variables as properties of the global object.

因此,由于无法有意地将某些东西从事物的coffee-script方面“泄漏”到全局名称空间中,所以需要将全局变量定义为全局对象的属性。

attach them as properties on window

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

This means you need to do something like window.foo = 'baz';, which handles the browser case, since there the global object is the window.

这意味着您需要做一些类似于window的操作。foo = 'baz';,用于处理浏览器情况,因为全局对象是窗口。

Node.js

In Node.js there's no window object, instead there's the exports object that gets passed into the wrapper that wraps the Node.js module (See: https://github.com/ry/node/blob/master/src/node.js#L321 ), so in Node.js what you would need to do is exports.foo = 'baz';.

在节点。没有窗口对象,而是导出对象被传递到包装节点的包装器中。js模块(参见:https://github.com/ry/node/blob/master/src/node.js#L321),所以在Node。需要做的是导出。foo =“巴兹”;。

Now let us take a look at what it states in your quote from the docs:

现在让我们来看看在你引用的文件中有哪些内容:

...targeting both CommonJS and the browser: root = exports ? this

…针对CommonJS和浏览器:root = export ?这

This is obviously coffee-script, so let's take a look into what this actually compiles to:

这显然是咖啡脚本,让我们来看看它实际上编译了什么:

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

First it will check whether exports is defined, since trying to reference a non existent variable in JavaScript would otherwise yield an SyntaxError (except when it's used with typeof)

首先,它将检查是否定义了导出,因为尝试在JavaScript中引用一个不存在的变量会产生一个SyntaxError(除了与typeof一起使用时)

So if exports exists, which is the case in Node.js (or in a badly written WebSite...) root will point to exports, otherwise to this. So what's this?

如果导出存在,这就是节点的情况。js(或写得不好的网站…)root用户会指向导出,否则会指向导出。所以这是什么?

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

Using .call on a function will bind the this inside the function to the first parameter passed, in case of the browser this would now be the window object, in case of Node.js it would be the global context which is also available as the global object.

在函数中使用.call将把函数内的this绑定到传递的第一个参数,如果是浏览器,那么现在它将是窗口对象,如果是节点。它是全局上下文,也可以作为全局对象使用。

But since you have the require function in Node.js, there's no need to assign something to the global object in Node.js, instead you assign to the exports object which then gets returned by the require function.

但是因为在Node中有require函数。js,不需要给节点中的全局对象赋值。而是分配给export对象,然后由require函数返回。

Coffee-Script

After all that explanation, here's what you need to do:

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

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

This will declare our function foo in the global namespace (whatever that happens to be).
That's all :)

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

#2


56  

To me it seems @atomicules has the simplest answer, but I think it can be simplified a little more. You need to put an @ before anything you want to be global, so that it compiles to this.anything and this refers to the global object.

在我看来,@atomicules有最简单的答案,但我认为它可以简化一点。你需要在所有你想要的东西之前加上一个@,这样它才能编译成这个。所有这些都指向全局对象。

so...

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

bawbag(5, 10)

compiles to...

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

and works inside and outside of the wrapper given by 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

#3


33  

Ivo nailed it, but I'll mention that there is one dirty trick you can use, though I don't recommend it if you're going for style points: You can embed JavaScript code directly in your CoffeeScript by escaping it with backticks.

Ivo实现了它,但是我要指出的是,您可以使用一个肮脏的技巧,但是如果您要使用样式点,我不建议使用这个技巧:您可以通过转义将JavaScript代码直接嵌入到CoffeeScript中。

However, here's why this is usually a bad idea: The CoffeeScript compiler is unaware of those variables, which means they won't obey normal CoffeeScript scoping rules. So,

但是,这就是为什么这通常是一个坏主意:CoffeeScript编译器不知道这些变量,这意味着它们不会遵守常规的CoffeeScript扫描规则。所以,

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

compiles to

编译,

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

and now you've got yourself two foos in different scopes. There's no way to modify the global foo from CoffeeScript code without referencing the global object, as Ivy described.

现在你有了两个不同作用域的foos。正如Ivy所描述的,如果不引用全局对象,就无法从CoffeeScript代码中修改全局foo。

Of course, this is only a problem if you make an assignment to foo in CoffeeScript—if foo became read-only after being given its initial value (i.e. it's a global constant), then the embedded JavaScript solution approach might be kinda sorta acceptable (though still not recommended).

当然,这只是一个问题,如果您在coffeest中向foo赋值,如果foo在给定初始值(即它是一个全局常量)之后成为只读的,那么嵌入的JavaScript解决方案可能是可以接受的(尽管仍然不推荐)。

#4


11  

You can pass -b option when you compile code via coffee-script under node.js. The compiled code will be the same as on coffeescript.org.

通过node.js下的coffee-script编译代码时,可以传递-b选项。编译后的代码将与coffeescript.org上的代码相同。

#5


9  

To add to Ivo Wetzel's answer

为了补充Ivo Wetzel的答案

There seems to be a shorthand syntax for exports ? this that I can only find documented/mentioned on a Google group posting.

似乎有一种简化的出口语法?我只能在谷歌群组发帖中找到文档/提及的。

I.e. in a web page to make a function available globally you declare the function again with an @ prefix:

也就是说,在web页面中,为了使一个函数具有全局可用性,您再次使用@前缀声明该函数:

<script type="text/coffeescript">
    @aglobalfunction = aglobalfunction = () ->
         alert "Hello!"
</script>

<a href="javascript:aglobalfunction()" >Click me!</a>

#6


9  

I think what you are trying to achieve can simply be done like this :

我认为你想要达到的目标可以简单地这样做:

While you are compiling the coffeescript, use the "-b" parameter.

在编译coffeescript时,使用“-b”参数。

-b / --bare Compile the JavaScript without the top-level function safety wrapper.

-b /——不使用*函数安全包装器编译JavaScript。

So something like this : coffee -b --compile somefile.coffee whatever.js

比如:coffee -b,编译文件。咖啡whatever.js

This will output your code just like in the CoffeeScript.org site.

这将输出您的代码,就像在CoffeeScript.org站点中一样。

#7


6  

If you're a bad person (I'm a bad person.), you can get as simple as this: (->@)()

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

As in,

如,

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

This works, because when invoking a Reference to a Function ‘bare’ (that is, func(), instead of new func() or obj.func()), something commonly referred to as the ‘function-call invocation pattern’, always binds this to the global object for that execution context.

这是可行的,因为当调用对函数“bare”(即func()的引用而不是新的func()或object .func())的引用(通常称为“Function -call invocation pattern”)时,总是将它绑定到执行上下文的全局对象。

The CoffeeScript above simply compiles to (function(){ return this })(); so we're exercising that behavior to reliably access the global object.

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

#8


3  

Since coffeescript is rarely used on it's own, you can use global variable supplied by either node.js or browserify (and any descendants like coffeeify, gulp build scripts, etc).

由于coffeescript很少单独使用,所以您可以使用任何一个节点提供的全局变量。js或browserify(以及任何类似于coffeeify、gulp构建脚本等的后代)。

In node.js global is global namespace.

在节点。js全局命名空间是全局命名空间。

In browserify global is equal to window.

在browserify全局变量中等于窗口。

So, just:

所以,只是:

somefunc = ->
  global.variable = 123

#1


416  

Since coffee script has no var statement it automatically inserts it for all variables in the coffee-script, that way it prevents the compiled JavaScript version from leaking everything into the global namespace.

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

So since there's no way to make something "leak" into the global namespace from the coffee-script side of things on purpose, you need to define your global variables as properties of the global object.

因此,由于无法有意地将某些东西从事物的coffee-script方面“泄漏”到全局名称空间中,所以需要将全局变量定义为全局对象的属性。

attach them as properties on window

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

This means you need to do something like window.foo = 'baz';, which handles the browser case, since there the global object is the window.

这意味着您需要做一些类似于window的操作。foo = 'baz';,用于处理浏览器情况,因为全局对象是窗口。

Node.js

In Node.js there's no window object, instead there's the exports object that gets passed into the wrapper that wraps the Node.js module (See: https://github.com/ry/node/blob/master/src/node.js#L321 ), so in Node.js what you would need to do is exports.foo = 'baz';.

在节点。没有窗口对象,而是导出对象被传递到包装节点的包装器中。js模块(参见:https://github.com/ry/node/blob/master/src/node.js#L321),所以在Node。需要做的是导出。foo =“巴兹”;。

Now let us take a look at what it states in your quote from the docs:

现在让我们来看看在你引用的文件中有哪些内容:

...targeting both CommonJS and the browser: root = exports ? this

…针对CommonJS和浏览器:root = export ?这

This is obviously coffee-script, so let's take a look into what this actually compiles to:

这显然是咖啡脚本,让我们来看看它实际上编译了什么:

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

First it will check whether exports is defined, since trying to reference a non existent variable in JavaScript would otherwise yield an SyntaxError (except when it's used with typeof)

首先,它将检查是否定义了导出,因为尝试在JavaScript中引用一个不存在的变量会产生一个SyntaxError(除了与typeof一起使用时)

So if exports exists, which is the case in Node.js (or in a badly written WebSite...) root will point to exports, otherwise to this. So what's this?

如果导出存在,这就是节点的情况。js(或写得不好的网站…)root用户会指向导出,否则会指向导出。所以这是什么?

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

Using .call on a function will bind the this inside the function to the first parameter passed, in case of the browser this would now be the window object, in case of Node.js it would be the global context which is also available as the global object.

在函数中使用.call将把函数内的this绑定到传递的第一个参数,如果是浏览器,那么现在它将是窗口对象,如果是节点。它是全局上下文,也可以作为全局对象使用。

But since you have the require function in Node.js, there's no need to assign something to the global object in Node.js, instead you assign to the exports object which then gets returned by the require function.

但是因为在Node中有require函数。js,不需要给节点中的全局对象赋值。而是分配给export对象,然后由require函数返回。

Coffee-Script

After all that explanation, here's what you need to do:

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

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

This will declare our function foo in the global namespace (whatever that happens to be).
That's all :)

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

#2


56  

To me it seems @atomicules has the simplest answer, but I think it can be simplified a little more. You need to put an @ before anything you want to be global, so that it compiles to this.anything and this refers to the global object.

在我看来,@atomicules有最简单的答案,但我认为它可以简化一点。你需要在所有你想要的东西之前加上一个@,这样它才能编译成这个。所有这些都指向全局对象。

so...

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

bawbag(5, 10)

compiles to...

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

and works inside and outside of the wrapper given by 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

#3


33  

Ivo nailed it, but I'll mention that there is one dirty trick you can use, though I don't recommend it if you're going for style points: You can embed JavaScript code directly in your CoffeeScript by escaping it with backticks.

Ivo实现了它,但是我要指出的是,您可以使用一个肮脏的技巧,但是如果您要使用样式点,我不建议使用这个技巧:您可以通过转义将JavaScript代码直接嵌入到CoffeeScript中。

However, here's why this is usually a bad idea: The CoffeeScript compiler is unaware of those variables, which means they won't obey normal CoffeeScript scoping rules. So,

但是,这就是为什么这通常是一个坏主意:CoffeeScript编译器不知道这些变量,这意味着它们不会遵守常规的CoffeeScript扫描规则。所以,

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

compiles to

编译,

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

and now you've got yourself two foos in different scopes. There's no way to modify the global foo from CoffeeScript code without referencing the global object, as Ivy described.

现在你有了两个不同作用域的foos。正如Ivy所描述的,如果不引用全局对象,就无法从CoffeeScript代码中修改全局foo。

Of course, this is only a problem if you make an assignment to foo in CoffeeScript—if foo became read-only after being given its initial value (i.e. it's a global constant), then the embedded JavaScript solution approach might be kinda sorta acceptable (though still not recommended).

当然,这只是一个问题,如果您在coffeest中向foo赋值,如果foo在给定初始值(即它是一个全局常量)之后成为只读的,那么嵌入的JavaScript解决方案可能是可以接受的(尽管仍然不推荐)。

#4


11  

You can pass -b option when you compile code via coffee-script under node.js. The compiled code will be the same as on coffeescript.org.

通过node.js下的coffee-script编译代码时,可以传递-b选项。编译后的代码将与coffeescript.org上的代码相同。

#5


9  

To add to Ivo Wetzel's answer

为了补充Ivo Wetzel的答案

There seems to be a shorthand syntax for exports ? this that I can only find documented/mentioned on a Google group posting.

似乎有一种简化的出口语法?我只能在谷歌群组发帖中找到文档/提及的。

I.e. in a web page to make a function available globally you declare the function again with an @ prefix:

也就是说,在web页面中,为了使一个函数具有全局可用性,您再次使用@前缀声明该函数:

<script type="text/coffeescript">
    @aglobalfunction = aglobalfunction = () ->
         alert "Hello!"
</script>

<a href="javascript:aglobalfunction()" >Click me!</a>

#6


9  

I think what you are trying to achieve can simply be done like this :

我认为你想要达到的目标可以简单地这样做:

While you are compiling the coffeescript, use the "-b" parameter.

在编译coffeescript时,使用“-b”参数。

-b / --bare Compile the JavaScript without the top-level function safety wrapper.

-b /——不使用*函数安全包装器编译JavaScript。

So something like this : coffee -b --compile somefile.coffee whatever.js

比如:coffee -b,编译文件。咖啡whatever.js

This will output your code just like in the CoffeeScript.org site.

这将输出您的代码,就像在CoffeeScript.org站点中一样。

#7


6  

If you're a bad person (I'm a bad person.), you can get as simple as this: (->@)()

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

As in,

如,

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

This works, because when invoking a Reference to a Function ‘bare’ (that is, func(), instead of new func() or obj.func()), something commonly referred to as the ‘function-call invocation pattern’, always binds this to the global object for that execution context.

这是可行的,因为当调用对函数“bare”(即func()的引用而不是新的func()或object .func())的引用(通常称为“Function -call invocation pattern”)时,总是将它绑定到执行上下文的全局对象。

The CoffeeScript above simply compiles to (function(){ return this })(); so we're exercising that behavior to reliably access the global object.

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

#8


3  

Since coffeescript is rarely used on it's own, you can use global variable supplied by either node.js or browserify (and any descendants like coffeeify, gulp build scripts, etc).

由于coffeescript很少单独使用,所以您可以使用任何一个节点提供的全局变量。js或browserify(以及任何类似于coffeeify、gulp构建脚本等的后代)。

In node.js global is global namespace.

在节点。js全局命名空间是全局命名空间。

In browserify global is equal to window.

在browserify全局变量中等于窗口。

So, just:

所以,只是:

somefunc = ->
  global.variable = 123