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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4214731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 11:25:28  来源:igfitidea点击:

How do I define global variables in CoffeeScript?

javascriptcoffeescript

提问by Handloomweaver

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:

通过 node.js 下的 coffee-script 进行编译,所以:

(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 中的导出对象上。如果您同时针对 CommonJS 和浏览器,则存在运算符(如下所述)为您提供了一种可靠的方法来确定在哪里添加它们: root = exports ? 这个

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

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

回答by Ivo Wetzel

Since coffee script has no varstatement 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.

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

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

因此,由于无法故意从咖啡脚本方面将某些内容“泄漏”到全局命名空间中,因此您需要将全局变量定义为global object 的属性。

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 objectis the window.

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

Node.js

节点.js

In Node.js there's no windowobject, instead there's the exportsobject 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';.

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

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 =exports ?这个

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 exportsis defined, since trying to reference a non existent variable in JavaScript would otherwise yield an SyntaxError (except when it's used with typeof)

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

So if exportsexists, 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?

因此,如果exports存在,在 Node.js 中(或在写得不好的网站...)中就是这种情况,root 将指向exports,否则指向this. 那是什么this

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

Using .callon a function will bind the thisinside the function to the first parameter passed, in case of the browser thiswould now be the windowobject, in case of Node.js it would be the global contextwhich is also available as the globalobject.

使用.call上的功能将绑定this功能里面第一个参数传递,在浏览器的情况下,this现在会是window对象,在Node.js的的情况下,这将是全球范围内它也可作为global对象。

But since you have the requirefunction in Node.js, there's no need to assign something to the globalobject in Node.js, instead you assign to the exportsobject which then gets returned by the requirefunction.

但是由于您require在 Node.js 中拥有该函数,因此无需为globalNode.js 中的对象分配任何内容,而是分配给该exports对象然后由该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 fooin the global namespace (whatever that happens to be).
That's all :)

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

回答by Billy Moon

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.anythingand thisrefers to the global object.

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

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

并在 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

回答by Trevor Burnham

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 globalfoofrom CoffeeScript code without referencing the global object, as Ivy described.

现在你foo在不同的范围内有两个s。有没有办法修改全球foo从CoffeeScript的代码而不引用全局对象,如常春藤描述。

Of course, this is only a problem if you make an assignment to fooin CoffeeScript—if foobecame 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).

当然,这只是foo在 CoffeeScript 中进行赋值时的问题——如果foo在被赋予初始值(即它是一个全局常量)后变为只读,那么嵌入式 JavaScript 解决方案方法可能有点可接受(尽管仍然不建议)。

回答by phongnh

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 上的相同。

回答by atomicules

To add to Ivo Wetzel's answer

添加到Ivo Wetzel 的答案

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

似乎有一种速记语法exports ? this,我只能在Google 群组帖子中找到记录/提及。

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

即在网页中使函数全局可用,您再次使用@前缀声明该函数:

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

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

回答by Sankalp Singha

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

我认为您想要实现的目标可以简单地这样做:

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

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

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

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

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

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

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

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

回答by ELLIOTTCABLE

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 Referenceto a Function‘bare' (that is, func(), instead of new func()or obj.func()), something commonly referred to as the ‘function-call invocation pattern', alwaysbinds thisto the global object for that execution context.

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

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 })(); 所以我们正在运用这种行为来可靠地访问全局对象。

回答by metalim

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

由于 coffeescript 很少单独使用,因此您可以使用global由 node.js 或 browserify 提供的变量(以及像 coffeeify、gulp 构建脚本等的任何后代)。

In node.js globalis global namespace.

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

In browserify globalis equal to window.

在 browserifyglobal中等于window.

So, just:

所以就:

somefunc = ->
  global.variable = 123