Alexander Gromnitsky
Alexander Gromnitsky

Reputation: 3029

module.exports & outside scope

foo.coffee:

class Foo
  constructor: ->
    console.log BAR

module.exports = Foo

main.coffee:

BAR = 1

class Bar
  constructor: ->
    console.log BAR

new Bar()

Foo = require './foo'
new Foo()

then

$ coffee main.coffee 
1
ReferenceError: BAR is not defined

Why BAR isn't accessible inside the instance of Foo? Can I make it 'visible' to Foo objects (besides of explicitly passing it to a constructor)?

Upvotes: 2

Views: 446

Answers (2)

Edwin Dalorzo
Edwin Dalorzo

Reputation: 78599

I think the problem is that in CoffeeScript when you declare a variable it is always compiled to a local variable.

Therefore, in your declaration above, when you do BAR=1 that gets compiled to var BAR=1. So, the variable is always scoped locally and it means it is not accessible to other modules.

So, the solution that Jed Schneider gave you is the correct one, with just one caveat, in Node.js, when you are in a module, the this reference points to the module.exports object and not to the global object as Jed seemed to suggest (this is a source of confusion between node.js and the browser, since in the browser it does behave as Jed explained).

So, this is always true

//module.js
console.log(this==module.exports) //yield true

Whereas within a function, the this keyword would point to the global object. So, this is also true:

//module.js
(function(){
   console.log(this==global); //yields true
})()

Being this the case, to solve your problem, you can use Jed Schneider approach, but make sure to wrap your code inside an IIFE so that your this points to global and not to module.exports.

So, this produces your expected results:

do ->
   @BAR = 1

   class Bar
      constructor: ->
         console.log BAR

   new Bar()
   Foo = require './foo'
   new Foo()

This produces the output

1
1

Upvotes: 2

Jed Schneider
Jed Schneider

Reputation: 14671

class Bar
   constructor: ->
     console.log @BAR

and then setting

@BAR = 1

should do what you expect. this is shorthand for this. which will place it on the global object, as you would expect constants to be defined. personally, I'd make a constants namespace and export that, the same as you do Foo.

Upvotes: 0

Related Questions