Rails - 从 JavaScript 调用 CoffeeScript
我在使用带有 CoffeeScript 的 Rails 3.1 时遇到了问题.如何从 .js.coffee 文件中的 .js.erb 文件调用函数?
说.js.coffee中的函数如下:
myName = ->鲍勃"
我想我可以像任何常规的 js 函数一样调用它,例如:
var theName = myName();
但这似乎不起作用.有什么想法吗?
或者是否可以在我的 .js.erb 文件中使用 coffeescript 以使所有内容都相同?
解决方案不能直接调用CoffeeScript函数的原因是CoffeeScript在编译时被封装在一个立即调用的函数中.这样做是为了防止您的代码污染全局命名空间.
这通常是 A Good Idea™,但您当然可以在需要时绕过它.如果您希望一个函数或其他变量可以在任何地方(即全局范围)访问,您可以简单地说
window.myName = ->鲍勃"
这样,函数被直接添加到全局作用域,你可以从任何地方调用它作为 window.myName()
(或者简单地作为 myName()
除非函数被本地函数遮蔽).
然而,为了保持全局命名空间尽可能干净,最好为自己定义一个命名空间(就像 jQuery 所做的那样,将 everything 放入 $
对象中).例如,在您的第一个 CoffeeScript 或 JavaScript 文件(即要加载的第一个文件)中,您可以这样做
window.myNamespace = {};
然后,当您希望在其他地方可以使用某些东西时,您可以将其添加到该命名空间:
window.myNamespace.myName = ->鲍勃"
然后您可以从任何地方调用它,使用 window.myNamespace.myName()
或简单地 myNamespace.myName()
.
或者,您可以在所有文件的顶部使用 CoffeeScript 的如果未定义或为空则赋值"运算符:
window.myNamespace ?= {} # 如果 myNamespace 不存在则创建它
首先评估哪个文件将创建缺少的 window.myNamespace
对象.后续代码只会看到它已经存在并跳过分配.重点是,无论评估顺序如何,它始终可用.
将 myNamespace
设为小写,因为它基本上是一个变量;不是构造函数/类
附录:您可以通过使用 -b/--bare
命令行开关来避免使用函数包装器,但是如上所述,包装器是个好东西.p>
I'm using Rails 3.1 with CoffeeScript and have run into a snag. How do I call a function from a .js.erb file that is located in a .js.coffee file?
Say the function in .js.coffee is the following:
myName = -> "Bob"
I would think I could just call it like any regular js function such as:
var theName = myName();
but that doesn't seem to work. Any ideas?
or is it possible to use coffeescript in my .js.erb file to make everything the same?
解决方案The reason you can't call the CoffeeScript function directly, is that CoffeeScript is wrapped in an immediately-invoked function when compiled. This is done to keep your code from polluting the global namespace.
This is generally A Good Idea™, but of course you can get around it when you need to. If you want a function or other variable to be accessible everywhere (i.e. global scope), you can simply say
window.myName = -> "Bob"
That way, the function is added directly to the global scope, and you can call it from anywhere as window.myName()
(or simply as myName()
unless the function's being shadowed by a local one).
However, to keep the global namespace as clean as possible, it's best to define a namespace for yourself (like jQuery does, by putting everything into the $
object). For instance, in your first CoffeeScript or JavaScript file (i.e. the first file to be loaded), you can do something like this
window.myNamespace = {};
Then, whenever you want something to be available elsewhere, you can add it to that namespace:
window.myNamespace.myName = -> "Bob"
And then you can call it from anywhere, using window.myNamespace.myName()
or simply myNamespace.myName()
.
Alternatively, you can use CoffeeScript's "assign if undefined or null" operator at the top of all your files:
window.myNamespace ?= {} # create myNamespace if it doesn't already exist
Whichever file gets evaluated first will create the missing window.myNamespace
object. Subsequent code will just see that it already exists and skip the assignment. Point is, it'll always be available, regardless of evaluation order.
Edit: Made myNamespace
lower-camelcase since it's basically a variable; not a constructor/class
Addendum: You can avoid the function wrapper by using the -b/--bare
command line switch, but as mentioned the wrapper is a good thing.
相关文章