How do I define global variables in CoffeeScript?
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.
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.
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
.
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';
.
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
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
)
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
?
(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.
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.
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 :)
CoffeeScript and Rails: Setting and getting global variables
I agree with Khaled's answer on the first question.
On the second one, I would rather rename the file to .js.coffee.erb so that it is preprocessed with erb first and write something like :
window.claimedCount = <%= @user.claims.count %>
global variable in node using coffeescript
exports
doesn't define "globals;" it defines "public" members of a module available via require
. Also, exports
is always initially defined and exports === this
, so (exports ? this)
isn't actually doing anything.
However, since globals are generally frowned upon (and do defeat some of the intents of Node's module system), a common approach for web applications is to define a custom middleware allowing access to the db
as a property of the req
or res
objects:
# app.coffee
app.use (req, res, next) ->
req.db = redis.createClient()
next()
# routes/index.coffee
exports.index = (req, res) ->
req.db.set('online', Date.now(), (err,reply) -> console.log(reply))
An example of this can be found in decorate.js
of npm-www
, the repository behind npmjs.org:
function decorate (req, res, config) {
//...
req.model = res.model = new MC
// ...
req.cookies = res.cookies = new Cookies(req, res, config.keys)
req.session = res.session = new RedSess(req, res)
// ...
req.couch = CouchLogin(config.registryCouch).decorate(req, res)
// ...
}
Though, if you'd still rather define db
as a global instead, Node.JS defines a global
variable you can attach to:
global.db = redis.createClient()
How to force a variable to be local in coffeescript?
This kind of error usually comes up when you aren't using appropriately descriptive variable names. That said, there is a way to shadow an outer variable, despite what the accepted answer says:
outer=1
f=->
do (outer) ->
local=1
outer=0
local+outer
This creates an IIFE, with outer
as it's one argument. Function arguments shadow outer variables just like the var
keyword, so this will have the behavior you expect. However, like I said, you should really just name your variables more descriptively.
Accessing global variables with node.js and CoffeeScript
You're close, but you need to change things just a little bit
# config.coffee
module.exports =
foo: "bar"
hello: "world"
db:
user: alice
pass: password1
# lib/a.coffee
config = require "../config"
# lib/b.coffee
config = require "../config"
# lib/db.coffee
dbconfig = require("../config").db
Passing global variable from controller to coffeescript
I recommend you this gem: Gon. Basically, in your controller:
@your_int = 123
@your_array = [1,2]
@your_hash = {'a' => 1, 'b' => 2}
gon.your_int = @your_int
gon.your_other_int = 345 + gon.your_int
gon.your_array = @your_array
gon.your_array << gon.your_int
gon.your_hash = @your_hash
The you can access those variables from your JavaScript
file:
alert(gon.your_int)
alert(gon.your_other_int)
alert(gon.your_array)
alert(gon.your_hash)
There is an interesting Railscast
with a detailed example: Passing Data to JavaScript
Can't read CoffeeScript global variable
Solved:
The dispatcher.bind
is an asynchronous function so at the time I access the variable from this function:
jQuery(document).ready ($) ->
root = (exports ? this)
console.log root.channel_user
channel_user is still not assigned.
To solve the problem i've added this line:
jQuery(document).ready ($) ->
dispatcher.bind "createuserchannel", () ->
root = (exports ? this)
console.log root.channel_user
In this way root.channel_user
will be called only when channel_user
has been setted.
Global variable in Coffeescript in Ruby on Rails
So window.s_area
is computed by display_on_map
:
display_on_map = (data,map, id, info, point_data, name_data, ayear) ->
#...
window.s_area = window.s_area + area
and display_on_map
is called in the success callback of an AJAX call:
load_track = (id,map, info, point_data, name_data, ayear) ->
callback = (data) -> display_on_map(data,map, id, info, point_data, name_data, ayear)
$.get '/tracksegments/'+id+'.json', {}, callback, 'json'
and you're using s_area
in a document-ready handler:
$ ->
$('#total').append('Sum of Area: '+s_area)
It is unlikely that the $.get
AJAX calls will complete before the document-ready handler is triggered so s_area
is still zero when you try to display it.
You could update the total as you calculate in display_on_map
, something like this:
window.s_area = window.s_area + area
$('#total').html("Sum of Area: #{window.s_area}")
That at least should get things happening in the right order.
PS:
- You can say
window.s_area += area
or justs_area += area
. - You can use string interpolation:
$.get "/tracksegments/#{id}.json", ...
and"Sum of Area: #{s_area}"
.
How to return a global variable value from inside a function in coffeescript?
Two things you have to do:
First, remove the ->
in
root.hello = -> 'hello world'
// ^^ remove this
That ->
means you're assigning a function to root.hello
.
Then, you need to add ()
after world
when doing the call, so you're calling world
, not just referring to it.
alert world()
// ^^ Add these
So:
$(document).ready ->
root = exports ? this
root.hello = 'hello world'
world = ->
root.hello
alert world()
Related Topics
Calling a Parent Window Function from an Iframe
How to Parse a CSV String With JavaScript, Which Contains Comma in Data
How to Use the Spacing Utility Classes in Bootstrap
How to Remove Item from Array by Value
For Loop For Htmlcollection Elements
Merge Two Array of Objects Based on a Key
JavaScript Function to Add X Months to a Date
Why Does String to Number Comparison Work in JavaScript
Jquery $(Document).Ready and Updatepanels
Angularjs Routing Without the Hash '#'
I Keep Getting "Uncaught Syntaxerror: Unexpected Token O"
Converting a Js Object to an Array Using Jquery
Best Way to Detect When a User Leaves a Web Page
Create an Array of Characters from Specified Range
What Is the JavaScript ≫≫≫ Operator and How to Use It
Dynamically Expand Height of Input Type "Text" Based on Number of Characters Typed into Field