首页 文章

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

提问于
浏览
312

在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中的exports对象上 . 存在运算符(如下所述)为您提供了一种可靠的方法来确定添加它们的位置,如果您的目标是CommonJS和浏览器:root = exports?这个

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

8 回答

  • 9

    由于咖啡脚本没有 var 语句,它会自动为咖啡脚本中的所有变量插入它,这样就可以防止编译好的JavaScript版本泄漏到 global namespace 中 .

    因此,由于无法有目的地从咖啡脚本方面向 global namespace 创建"leak",因此需要将全局变量定义为 global object 的属性 .

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

    这意味着您需要执行 window.foo = 'baz'; 之类的操作,它处理浏览器的情况,因为 global objectwindow .

    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 context ,它也可用作 global 对象 .

    但是由于你在Node.js中有 require 函数,所以不需要为Node.js中的 global 对象赋值,而是分配给 exports 对象,然后由 require 函数返回 .

    咖啡脚本

    完成所有解释之后,这就是您需要做的事情:

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

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

  • 3

    对我来说,似乎@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);
    

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

    Ivo钉了它,但我会提到你可以使用一个肮脏的技巧,但是如果你想要使用样式点我不推荐它:你可以通过使用反引号转义它来直接在你的CoffeeScript中嵌入JavaScript代码 .

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

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

    编译成

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

    现在你已经有了两个不同范围的 foo . 正如Ivy所描述的那样,没有引用全局对象就无法修改CoffeeScript代码中的全局 foo .

    当然,如果你在CoffeeScript中对 foo 进行赋值,这只是一个问题 - 如果 foo 在给定其初始值后变为只读(即它是一个全局常量),那么嵌入式JavaScript解决方案方法可能有点可接受(虽然仍然不推荐) .

  • 6

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

  • 33

    要添加到Ivo Wetzel's answer

    似乎有 exports ? this 的简写语法,我只能在Google group posting上找到记录/提及的语法 .

    即在网页中创建一个功能在全局可用时,您使用 @ 前缀再次声明该函数:

    <script type="text/coffeescript">
        @aglobalfunction = aglobalfunction = () ->
             alert "Hello!"
    </script>
    
    <a href="javascript:aglobalfunction()" >Click me!</a>
    
  • 57

    我认为你想要实现的目标可以简单地完成:

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

    -b / --bare 在没有顶级功能安全包装的情况下编译JavaScript .

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

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

  • 417

    如果你是一个坏人 . ),你可以这样简单: (->@)()

    如,

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

    这是有效的,因为当调用 ReferenceFunction '裸'(即 func() ,而不是 new func()obj.func() )时,通常称为'函数调用调用模式',总是将 this 绑定到全局对象 . execution context .

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

  • 11

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

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

    在browserify中 global 等于 window .

    所以就:

    somefunc = ->
      global.variable = 123
    

相关问题