module.exports&外部范围

时间:2014-06-18 11:32:17

标签: javascript node.js coffeescript

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

然后

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

为什么在BAR的实例内无法访问Foo? 我可以让它Foo对象“可见”(除了明确地将它传递给构造函数)吗?

2 个答案:

答案 0 :(得分:2)

我认为问题在于,当您声明变量时,在CoffeeScript中,它总是被编译为局部变量。

因此,在上面的声明中,当您BAR=1编译为var BAR=1时。因此,变量总是在本地范围内,这意味着其他模块无法访问它。

所以,Jed Schneider给你的解决方案是正确的,只有一个警告,在Node.js中,当你在一个模块中时,this引用指向module.exports对象而不是Jed似乎暗示的global对象(这是node.js和浏览器之间混淆的根源,因为在浏览器中它确实像Jed解释的那样)。

所以,这总是如此

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

在函数中,this关键字将指向全局对象。所以,这也是如此:

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

就这种情况而言,为了解决您的问题,您可以使用Jed Schneider方法,但请确保将代码包装在IIFE内,以便this指向global和不要module.exports

因此,这会产生您的预期结果:

do ->
   @BAR = 1

   class Bar
      constructor: ->
         console.log BAR

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

这会产生输出

1
1

答案 1 :(得分:0)

class Bar
   constructor: ->
     console.log @BAR

然后设置

@BAR = 1

应该做你期望的。这是this.的简写,它将把它放在全局对象上,就像你期望的那样定义常量。就个人而言,我会创建一个常量命名空间并导出它,就像你Foo一样。