How to Define Global Variables in Coffeescript

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 just s_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



Leave a reply



Submit