module.exports

#javascript #node.js #coffeescript

#javascript #node.js #coffeescript

Вопрос:

foo.coffee:

 class Foo
  constructor: ->
    console.log BAR

module.exports = Foo
  

главное.кофе:

 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 объектов (помимо явной передачи его конструктору)?

Ответ №1:

Я думаю, проблема в том, что в CoffeeScript, когда вы объявляете переменную, она всегда компилируется в локальную переменную.

Поэтому в вашем объявлении выше, когда вы это делаете BAR=1 , компилируется в var BAR=1 . Таким образом, переменная всегда ограничена локально, и это означает, что она недоступна для других модулей.

Итак, решение, которое дал вам Джед Шнайдер, является правильным, с одной оговоркой, в Node.js , когда вы находитесь в модуле, this ссылка указывает на module.exports объект, а не на global объект, как, казалось, предполагал Джед (это источник путаницы между node.js и браузер, поскольку вбраузер ведет себя так, как объяснил Джед).

Итак, это всегда верно

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

В то время как внутри функции this ключевое слово будет указывать на глобальный объект. Итак, это тоже верно:

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

В этом случае, чтобы решить вашу проблему, вы можете использовать подход Джеда Шнайдера, но обязательно оберните свой код внутри IIFE, чтобы this он указывал на global , а не на module.exports .

Итак, это дает ожидаемые результаты:

 do ->
   @BAR = 1

   class Bar
      constructor: ->
         console.log BAR

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

Это приводит к выводу

 1
1
  

Комментарии:

1. отличное объяснение. Я не знал, что я на самом деле привязан к module.exports объекту в node (за вычетом моей специальности), но это явно имеет смысл. 1 за исправление.

Ответ №2:

 class Bar
   constructor: ->
     console.log @BAR
  

а затем настройка

 @BAR = 1
  

должен делать то, что вы ожидаете. это сокращение для this. which поместит его в глобальный объект, поскольку вы ожидаете, что будут определены константы. лично я бы создал пространство имен constants и экспортировал его так же, как и вы Foo .

Комментарии:

1. Проблема не в классе Bar, а в Foo . И если я напишу @BAR = 1 в main.coffee и @BAR в foo.coffee, он печатает «неопределенный».