Asked  7 Months ago    Answers:  5   Viewed   54 times

On 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:

(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

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

 Answers

94

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 :)

Tuesday, June 1, 2021
 
eek
answered 7 Months ago
eek
43

i was finally able to get it to work with this

   $app->hook('slim.before.dispatch', function() use ($app) { 
       $current_company = null;
       if (isset($_SESSION['company_id'])) {
          $current_company = Company::find($_SESSION['company_id']);
       }
       $app->view()->setData('current_company', $current_company);
    });
Wednesday, March 31, 2021
 
Crashthatch
answered 9 Months ago
87

To use global variables inside a function, you need to do global <varName> inside the function, like so.

testVar = 0

def testFunc():
    global testVar
    testVar += 1

print testVar
testFunc()
print testVar

gives the output

>>> 
0
1

Keep in mind, that you only need to declare them global inside the function if you want to do assignments / change them. global is not needed for printing and accessing.

You can do,

def testFunc2():
    print testVar

without declaring it global as we did in the first function and it'll still give the value all right.

Using a list as an example, you cannot assign a list without declaring it global but you can call it's methods and change the list. Like follows.

testVar = []
def testFunc1():
    testVar = [2] # Will create a local testVar and assign it [2], but will not change the global variable.

def testFunc2():
    global testVar
    testVar = [2] # Will change the global variable.

def testFunc3():
    testVar.append(2) # Will change the global variable.
Saturday, June 19, 2021
 
Akarun
answered 6 Months ago
22

Never add event listeners in HTML. Add them in your JavaScript, preferably in the same scope in which you define the event handler.

printAValue = () -> 
    test = new TestClass()
    test.printValue()

document.body.addEventListener('load', printAValue, false)

If you absolutely need to export something to the global scope, export to the window object:

window.printAValue = () -> 
    test = new TestClass()
    test.printValue()
Tuesday, August 10, 2021
 
csi
answered 4 Months ago
csi
15

Just add a true as the last line of your function, and coffeescript will compile the JS to return that instead:

$("table.tableview th input:checkbox").live 'click', -> 
    checkedStatus = this.checked
    $("table.tableview tbody tr td:first-child input:checkbox").each ->
        this.checked = checkedStatus
    true

In other words, CoffeeScript always returns the result of the last line (like Ruby does)


Edit (after the question was updated):

Again, you can't keep CoffeeScript from returning the value of the last line in a function - part of the point of CoffeeScript is that it does exactly that.

CoffeeScript has significant whitespace, so indentation is what says what belongs together - your example is is actually correct:

$("table.tableview th input:checkbox").live 'click', -> 
    checkedStatus = this.checked
    $("table.tableview tbody tr td:first-child input:checkbox").each ->
        this.checked = checkedStatus
        true // cause this function (the each-iterator) to return true
    true // causes the click handler function to return true

There's no difference between this and just writing return true in a function like you would in javascript. You just use whitespace instead of {} to make code blocks.

Tuesday, August 17, 2021
 
Hugo
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share