Why does accessing variables declared without `var` work without having to use `require` in other files? - node.js

Here's an example
$ cat main.js
App = {
version : 1.1
};
require('./mymod.js');
$ cat mymod.js
console.log(App.version);
$ node main.js
1.1
Note how I declared App in main.js without var. This allowed me to access App from mymod.js without having to call require. If I declare App with a var, this won't work.
I want to understand why this happens? Is it the intended behaviour for node.js or a bug? Is this behavior consistent with ECMAScript or CommonJS standards?
This trick gives a powerful mechanism to circumvent the require module system of node.js. In every file define your objects and add them to the top level App namespace. Your code in other files will be automatically have access to those objects. Did I miss something?

If you assign a variable without using var, it is automatically a global variable. That's just the way JavaScript works. If you put 'use strict'; (quotes required) at the top of your js file, this becomes an error instead.

All has to do with local scope vs global scope.
You can even do this (which is much neater):
app.js:
exports = {
version : 1.1
};
main.js:
var App = require('./app.js');
console.log(App.version);

Defining a variable without a preceding var will place it into the global namespace which is visible to all of your JavaScript code.
While this may seem a useful feature, it is generally considered bad practice to "pollute" the global namespace and can lead to subtle, hard-to-locate bugs when two non-related files both rely upon or define variables with the same name.

In nodeJS environment there is a global scope referenced by 'global' , just like the way we have 'window' in browser environments. In effect every javascript host enviroments always start with creating a global object.
When require('main.js') is executed, there is this following function that is created and executed against the global scope 'global'.
(function(exports,...){
//content of main.js
App = {
version : 1.1
};
})(module.exports,..);
When the above function is executed and since there is no var declaration for App , a property with name 'App' is created on global object and assigned the value.This behavior is according to ECMA spec.
That is how the App gets into global scope and is accessible across all modules.
require has been introduced to standardize development of modules that can be ported and used.

Related

nodejs: how to use literals in external require?

Here is my example:
var name="Doe";
var template = require('./template.txt');
and template.txt contains:
`hello ${name}`
I got the error: name is not defined.
Any idea ?
Well you literally want to take JS code from a .txt file and run it, so you need the infamous eval
var name="Doe";
var template = require('fs').readFileSync('./template.txt');
template = template.toString().trim();
console.log(eval(template)) // will output: hello Doe
Although it can be dangerous to run JS code like this, if the templates are files that are in your control and written by you, then I guess it can be done.
Ofcourse you could simply use a template engine like EJS or nunjucks
From the Node.js documentation:
The module wrapper
Before a module's code is executed, Node.js will
wrap it with a function wrapper that looks like the following:
(function(exports, require, module, __filename, __dirname) {
// Modulecode actually lives in here
});
By doing this, Node.js achieves a few
things:
It keeps top-level variables (defined with var, const or let) scoped
to the module rather than the global object.
It helps to provide some
global-looking variables that are actually specific to the module,
such as:
The module and exports objects that the implementor can use to export
values from the module.
The convenience variables __filename and
__dirname, containing the module's absolute filename and directory path.
and globals:
In browsers, the top-level scope is the global scope. This means that
within the browser var something will define a new global variable. In
Node.js this is different. The top-level scope is not the global
scope; var something inside a Node.js module will be local to that
module.
So when we define a variable in one module, the other modules in the program will not have access to that variable, but you can declare your variable without var and it will be defined as a global.
More info in this thread: Where are vars stored in Nodejs?

Inject a global variable into node context

Could i inject a global variable into node context, like "document" in html's script, which any javascript files could access this variable, and it isn't needed to import or require it?
//var document = require('document') // i don't need to require it by myself
document.findById('111')
To create a global in node.js, you assign to the global object.
// define global
global.myGlobal = 3;
// then use it anywhere
console.log(myGlobal);
Here's a good article on module-level variables and globals: Using global variables in node.js.
FYI, the node.js module architecture makes it so you do not need to use globals at all. You can simply require() in shared modules in order to share variables. If you're new to node.js, this may seem a bit odd and a bit inefficient, but you will get used to it and it is the preferred way to develop in node.js because it leads to modularity, testability and robust code.
Here's an interesting article on: Why global variables are bad.

node.js setting a global variable

I'm new to node js. I searched a lot on stack overflow on this question below, none what I need.
I have an app.js file which initiates node server and a router file. I want to be able to store a global value once and shared across other server side .js files which contains my functions. I also want this variable to be accessible in my .jade file. (I use express BTW)
Is there a way to accomplish this?
Thanks.
The Node.js documentation says under Module Caching
Caching 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.
Multiple calls to require('foo') may not cause the module code to be
executed multiple times. This is an important feature. With it,
"partially done" objects can be returned, thus allowing transitive
dependencies to be loaded even when they would cause cycles.
If you want to have a module execute code multiple times, then export
a function, and call that function.
Which means you can easily expose a global object simply by putting it in its own module.
//config.js
var config = {
dbUrl: 'mogodb://localhost:2107/persons'
};
module.exports = config;
And then when you want to gain access to that object, you simply do:
var config = require('./config');
And that's done, you get access to the same instance everywhere.
You'll want to limit the usage of global vars in Node. This is because unlike any other server side language, Node is a persistent process that share all request. So you cannot setup user state globally as those will be shared across all user accessing your site.
In raw node, there's two global context:
global.foo = 'bar';
// and the process object
process.some_var = 1;
In Express, you can setup application wide vars using app.set
But, most of the time you'll want to share data by adding them to the request or the response objects. That is because those objects are "user" specifics, unlike the global namespace.
For the template, you'll always want to pass in the context:
app.render('email', Object.assign( aSharedObject, {
specific: 'values'
}));
i would use process.env or if you are using nconf put it into the app configuration as Jordan said, globals are BAD idea, also if you don't want to include nconf or any other conf module or use process.env then you can create a module and export a set of getters and setters to handle the value

Global function in express.js?

How can I define a global function in express.js, that without require I can call it
"How" is simple enough:
global.fnName = function(){ return "hi"; }; // Andreas Hultgren's answer
But you don't need the global prefix; the thing about the global object is ...
fnName = function(){ return "hi"; }; // i.e. don't do: var name = function(){ ... };
console.log(fnName()); // this prints "hi"
console.log(global.fnName()); // this also prints "hi" - it was assigned to global.
"Without require" is a separate consideration: if you don't use require there is no guarantee your "globals" will have been declared by the time you need them. It enforces loading order of dependencies, among other things.
"Why am I" and "Is it correct to" are now hidden questions you should consider. It is accepted in javascript that Global Variables ...
... should be reserved for objects that have system-wide relevance and they should be named to avoid ambiguity and minimize the risk of naming collisions - Angus Croll, Namespacing in Javascript
i.e. global truly is Global: it is used by every author of every plugin or library you pull in to your application, not just you. Naming collisions between global variables break your application. This applies equally in node.js.
Global variables are also thought of as a code smell. In the detail sections below here you will see you can quickly get into trouble by using global variables, and they should really be treated as something that pushes you towards dependency injection and/or namespaces and modules.
Node.js and express - global vars and functions
Here's a good rule: if you upload it to a web server, or share it with other people, don't use global variables.
global is permissible in tiny "Saturday afternoon" apps in node.js with express.js, but tend to cause problems later if they get adopted into production. Therefore:
Modules and exports is best practice.
Injection should also be used to reduce coupling between javascript files. But in all cases you will usually need require to ensure they exist by the time you need them:
You should really consider app.locals data, and/or middleware functions, for anything that is view data related.
// call this as a function with an input object to merge
// the new properties with any existing ones in app.locals
app.locals.({
sayHello: function() { return "hi"; }
});
// now you can also use this in a template, like a jade template
=sayHello()
If you are creating global vars/functions for configuration settings purposes the below comments about namespaces still apply, and there are conventions emerging such as config.json files (still using require) for settings that are globally accessed.
Global variables - simple case
It is simple enough to declare a global variable in javascript, and for a function the process is no different. Simply omit the var keyword which would normally force a local scope on the declaration:
// app.js
blah = "boo";
sayHello = function(string toWho) { return "hello " + toWho; }
getVersion = function() { return "0.0.0.1"; }
// routes/main.js
console.log(blah); // logs: "boo"
console.log(global.blah); // logs: "boo"
console.log(sayHello("World")); // logs: "hello World"
console.log(global.sayHello("World")); // logs: "hello World"
console.log(getVersion()); // logs: "0.0.0.1"
But what if two separate plugins in your project use a global getVersion function - how do you get the right version number? Also, how do you ensure that getVersion exists before you need it, or exists at all?
Why do we need require?
To quote the nodejitsu docs the built in require function ...
... is the easiest way to include modules that exist in separate files. The basic functionality of require is that it reads a javascript file, executes the file, and then proceeds to return the exports object
"So", you may ask, "require just makes sure that a module from another file is included? Why bother?" It's better than that: you can make a whole folder a module, making your code easier to organise and test test test, it will recognise various extensions for file modules, not just .js, and it will look in various folders as well. Of course, it caches as well.
So, now that require has found your module, it ensures the code inside it is executed, and puts the objects your created into a "namespace":
// module file ./myModule.js
exports.blah = "boo";
exports.sayHello = function(string toWho) { return "hello " + toWho; }
// routes/main.js
var demoModuleReference = require('./myModule.js');
console.log(demoModuleReference.blah); // logs: "boo"
console.log(demoModuleReference.sayHello("World")); // logs: "hello World"
In that sample, demoModuleReference is an object that looks like:
{
blah: "foo",
sayHello: [Function]
}
Why modules and not global variables (a.k.a namespacing and "Global is the new private")?
Seems complicated now? Surely global variables are easier? requires ensures the following:
It ensures ordered loading of dependencies
It prevents variable name conflicts within global through the exports object.
This application at mankz.com (chrome or firefox only) is fascinating. Depending on how you use your js code, you are very likely to have variable name conflicts within the global scope. Name conflicts come from everywhere. In a browser, for instance, they can come from extensions. node.js is slightly different, but it is becoming more and more extended by compatible plugins as time goes on (you can load jquery in right now, for example). As the versions go on frameworks will get added, and name collisions in global will become more likely. My last run of that app in chrome showed over 1200 global namespace variables.
Namespaces - why?
This global namespace pollution was publicised early on by Douglas Crockford through Eric Miraglia in the article "A JavaScript Module Pattern". In summary:
All objects that need to be used between js files are really global
So, create a namespace object that will be unique
Assign the return value an anonymous function
Add private methods and variables inside that function
Do something useful with the pattern
Example:
ANDYBROWNSONICSUITE.BoomBox.SoundModule = function () {
var privateField = "can't touch this";
return {
play: function() {
console.log(privateField);
}
}
}
Why is this good?
Now you have only increased the global namespace members in the world by one, but this member contains as many items as you like.
Your application is far less likely to clash with other namespaces
It's a pattern, other frameworks expect you to use it to interact with them properly. In that reference, jQuery is a browser plugin, but you can use it with node and therefore your app, so the library interactivity policy statement is a perfect example.
It's a pattern, if we all follow it we our programs are all more likely to get along
When you read the Crockford reference along with the Croll reference (Direct Assignment section) I mentioned at the start, you see why it looks this complicated rather than just doing: sound.play = function() { ... } - ease of maintenance, refactoring the namespace etc. being just one reason.
Summary
In summary:
Can I create globals? Yes, it's simple, omit the var keyword before the declaration.
Should I create globals? You should use the module pattern, which is implicitly supported by node, and by express
Why am I creating globals? If it's for configuration, use a config namespace (e.g. How to store Node.js deployment settings/configuration files?)
You can:
global.name = function(){};
But you really should avoid using globals, even if it's possible to use them.

Is there a better way to structure global variables in Node.js?

Trying to understand what would be the best way to structure some variables. For example in my Node.js Express app, I have the following in app.js:
var poolModule = require('generic-pool');
global.pools = {
/* ... */
};
Where pools is my global variable that keeps track of MySQL and Redis pools. I am also wondering if I can do the same with actual Redis and MySQL objects (and maybe configs variable) so I don't have to require them all over the app. And since they are going to be used the most.
Is this bad practice, and if yes, what's a better way to structure this kind of code?
Edit: added global.
If you require a file you are actually always requiring the same object. So that means you can do:
module.exports = {
// same object for everybody that requires me
};
You have the right idea, but you want to use module.exports to export your object as a module. The CommonJS approach is to have local variables within the module and exported variables for use outside the module. In this way modules can access each others' variables through the use of require. These variables aren't really "global", but in a way are more like "friend" classes in C++. You can in fact have your poolModule do more than store variables for you--you could put methods and other functionality in there too and make it reusable across your whole application.

Resources