10

In my server.js file I included the Underscore.js library.

var _ = require('underscore')

I have my routes like this:

// require routes
require('./routes/document');

In the document route, I want to use Underscore.js. But it seems like the _ variable is not inherited/inside the document scope. Does that mean I have to set the _ variable on every single required route? Or is there a more intelligent way to do this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Harry
  • 52,711
  • 71
  • 177
  • 261

3 Answers3

10

Yes, you should set the _ in the files that needs it to be available.

Alternatively, you can put it in the global scope by removing the var part.

_ = require('underscore');
require('./routes/document'); // _ will be visible in document as well
Decko
  • 18,553
  • 2
  • 29
  • 39
  • 7
    If you use `global._ = require("underscore");` then the meaning becomes more obvious and there is no "doubt" as to whether you forgot the `var` statement. – Raynos Apr 09 '11 at 19:19
  • 4
    Removing `var` places it in module scope not global scope. – Raynos Jun 22 '11 at 08:46
  • @Raynos What is meant by "module scope"? Does that mean that only this module, and all modules required from this module can access it? – MiniGod Oct 04 '12 at 00:32
  • @Raynos If you do the experiment, you will see that removing var makes the variable available across all modules. This is the global scope. – chris Jul 27 '15 at 08:21
  • Another caveat I noticed is that the node.js command line already defines a global variable called _ which refers to the result of the last command entered in the console. This variable cannot be overridden by assigning it, which really confused me for a while. – chris Jul 27 '15 at 08:22
4

Check the Node.js module documentation where require() is thoroughly explained.

http://nodejs.org/docs/v0.4.5/api/modules.html

As for your specifics:

Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.

Hence, if you require('underscore') in both your parent library and './routes/document', only one instance of the underscore module will be loaded and hence. Both variables will be in fact the same object.

And by the way, you don't want to define variables in the global scope as it might generates side effects and potentially overwrite properties in other modules.

Finally, the util module provides an inherits method to subclass another constructor and inherit from its prototypes.

http://nodejs.org/docs/v0.4.5/api/util.html#util.inherits

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pdeschen
  • 1,369
  • 15
  • 17
  • `_` is a general utility library. If you use, you would use it through your entire code set. It is used to "enhance" JavaScript. I think it's valid to include it globally as otherwise I would `require` it in _every single_ node.js file. In most cases yes it should be avoided. – Raynos Apr 09 '11 at 19:18
  • 2
    @Raynos I understand it is a general purpose library. My answer was in the general form regardless of the required module. Nevertheless, I wouldn't augment the global scope anyways. :-) – pdeschen Apr 09 '11 at 20:36
  • how do you avoid writing `require("global-common");` in all your files. (Assuming you have something thats included in every file) – Raynos Apr 09 '11 at 20:47
  • 2
    @Raynos What is the actual problem with adding such require() statements whenever you actually need a specific module? It's part of the contract, that is, looking up at a given module, one becomes aware of its dependencies looking at the require statements. No hidden magic. In java/python/scala/etc you import, in C/C++ you include, in perl you use, in ruby you require and in node/commonjs you also require(). Well, that's my perspective. Your millage may vary. – pdeschen Apr 09 '11 at 21:24
  • I like DRY. I find the fact that I have to `import System` in other languages also a pain. I like having the ability to make some common dependencies project global rather then having to include them in every file. – Raynos Apr 09 '11 at 21:36
1

As far as I know Node.js engine "requires/charges" a module/file.js in a different scope (I don't know exactly how), for security reasons (imagine a module could change the variables were it's required. That would be dangerous! More information about this concern: Information hiding).

The only exception are global Node.js objects that are exposed into the module scope.

A global object is, precisely the object "global", and everything you define without var keyword actually is added to that global object:

foo_var = "Whatever"

means that:

console.log(global.foo_var) // Logs "Whatever"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
R01010010
  • 5,670
  • 11
  • 47
  • 77