Are there any security issuses or something with using global variables and assignig modules to global variables in nodejs?
example:
client = new Client();
Without the var statement, so i can use it everywhere?
It's not that it's a security problem, it's considered bad practice though and it can lead to other problems such as trying to override a Node.js global variable.
Try not to pollute the global namespace and if you really really need global variables, just use one with sub-objects.
I don't think there are security issues per se, but you will be polluting the global namespace. As your project grows (especially with more than one programmer) the risk of conflicts gets bigger. And what if you later on add a third party library to your project that has a variable named 'client'?
I've been using Node for a couple of years and I had the same "problem" you have and is frustrating. Nevertheless I can give you the solution I reached and it works for me.
Node doesn't allows global variables in the way you ask since variables defined as global in a module are global only for that module. But exists a GLOBAL object that ban be used for what you need.
Global variables are a bad idea in general (always), but having a global cache of useful functions in it's own namespace is not a crime at all since it will not override anything and lets you use it along your code. So I'll tell you what I do to share functions and objects between modules and keep source organized (that's important for me at least!):
1st Create a resource file where you place all important functions and objects you want to share across your code. I call mine "R.js", R from Resources
2st Define the "R" object that will store all functions and objects and assign it to node's GLOBAL object:
var R = {};
GLOBAL.R = R; // Adds resource module to global
3rd For sake of simplicity and avoid extra requires all arround the code, I do all needed requires inside R.js. After that you only need to use them with R.require_variable.function_or_property
// All needed requires
R.fs = require('fs');
R.net = require('net');
R.http = require('http');
R.dbClient = require('mysql').Client;
...
4th Create the shared functions, variables and objects you like inside the R object
5th Where needed arround your code, require the R.js file and access to it's member by using the R object
R.<property_or_function>
2 warning notes.
Remember to always call shared functions or user shared objects placind "R." in front of it
Althought you can assign new functions, objects and properties to R object anywhere this can lead to the same inconsistencies you would have with global variables if you don't plan it in advance - i.e. you call a shared function before assigning it to R - so as a methodology, create everything in the R.js file instead of doing it all arround your code. This way all shared things will be in R.js and that is the only place to look for shared code.
Related
I've learned that using globals is a bad idea in Javascript because there's the risk of collisions with dependencies.
Can I use var at the global scope as an alternative to this? I want to avoid the pitfalls of globals, but doing this seems much easier than passing along all my custom objects as parameters to functions. I have objects which are partially defined in many different files.
Can I use var at the global scope as an alternative to this?
var in global scope creates a global variable. So it's exactly the same and not in any way better.
If you are working with Node, there isn't really a need for globals. Every module should require all of its dependencies.
var sym = Symbol();
is window['sym'] which is already global scope.
But MDN says:
The above syntax using the Symbol() function will not create a global symbol that is available in your whole codebase. To create symbols available across files and in a global scope-like environment, use the methods Symbol.for() and Symbol.keyFor() to set and retrieve symbols from the global symbol registry.
sym is already in global scope in a browser, with above declaration syntax.
What is global symbol registry?
Each html document is tied with window object.
So,
In a browser world, How does this scope of symbol availability across files/realms different from global scope(window object)?
var sym = Symbol();
is creating a new property sym in dictionary(window), which is in global scope, where value can be accessed as window['sym'].
Well, no. It does create a symbol and assigns it to a local variable named sym. Only if you are executing this code in the global scope (which you usually wouldn't, for modularity) it does create a property on the global object of your realm (js environment). Notice that this global object is not always window like in web pages, it depends on your environment.
What is global symbol registry?
It's a registry (think: dictionary) for symbols that you can access via a string key. And "global" does in this case mean even more global than a global scope, the global symbol registry does span all realms of your engine. In a browser, the web page, an iframe, and web worker would all have their own realm with own global objects, but they could share symbols via this global registry.
And this sharing is exactly the purpose. If you'd otherwise put
var sym1 = Symbol("shared");
var sym2 = Symbol("shared");
in two places, then sym1 !== sym2. If you've got a shared object, using the symbols as property keys would create two different properties. If however you do
var sym1 = Symbol.for("shared");
var sym2 = Symbol.for("shared");
then sym1 === sym2 and when you use it you'll always get the same property.
See also Crossing realms with symbols on 2ality and Symbols and why they're awesome for more examples, including the well-known symbols which are similarly global.
The global symbol registry is just a convenient global repository for symbol instances. You could implement one yourself if you wanted to, but having such a repository built-in means that the runtime can use it as a place to publish symbol instances that have particular meaning for a given context.
In your own application, you can decide that some types of objects will have certain properties accessible via some symbol. All your code can find those symbols via Symbol.for():
var SPECIAL_PROPERTY = Symbol.for("mySpecialProperty");
// ...
var specialVal = someObject[SPECIAL_PROPERTY];
Because the registry is global, that works regardless of scope or compilation unit.
By making the registry part of the runtime, an environment like Node.js can use the symbol mechanism to extend objects without fear of causing problems for legacy code. Like, if Node wanted to make it such that you could find out how much memory an object used, they could invent a symbol, put it in the registry, and document the registry key. Any code could then use that:
var objectSize = myObject[Symbol.for("memory_use")];
(That's totally made up; it might make no sense at all for Node to do that particular thing.) Because of the way symbols work as property keys, code that doesn't know about that won't experience any weird issues should the objects it manipulates suddenly start carrying around that extra property.
(Of course, the namespace of the symbol registry itself is just a namespace, so collisions would have to be dealt with there in pretty much exactly the same way we deal with name collisions in the window object.)
Global symbol registry exists across all iframes in a window. (As symbols can't be passed across workers, there's no observable concept of it being identical across workers, barring the existence of sidechannel inspections, eg by memory probing.)
<script>
document.head.appendChild(document.createElement('iframe'))
.src=`javascript:
alert(parent.Symbol===Symbol) /*false*/
,alert(parent.Symbol.for('a') === Symbol.for('a')) //true
`
</script>
Symbol.for is not much different from implementing your own cache using an object reference. It's merely in-built and thus more convenient. Instead of Symbol.for('a'), you can simply do:
obj['a']? obj['a'] : obj['a'] = Symbol()
.and maintain a ref to obj.
In fact, since javascript does not provide an API to remove symbols in the global registry, its beneficial to do it the manual-caching way if you need to manually manage the memory of the registry.
So in Firefox extensions it's encouraged for your extension's objects to live in sub-objects like com.contoso.myExtension . That way you have not put any objects in the global namespace and extensions generally stay out of each other's hair. (At least in the common browser.xul window)
But from what I have understand about Javascript code modules (JSMs), is that while the module itself is working in a separate namespace, the symbols that it exports will end up in the global namespace of whatever code imports it. Furthermore, it's impossible for an extension to be "nice" and only try to build sub-objects; those exported symbols will just whack whatever global variables already existed. Also you can't export a symbol like com.contoso.myExtension. It's only a simple global variable.
So what's the protocol for playing nice when using JSMs? Just make really long variable names and hope they won't collide?
First off, I haven't seen a hard a true standard for how to handle this. But we can definitely do much better than just long variable names...
You are correct about the Javascript Code Modules living in a separate namespace (so to speak), however when you import them, you don't have to import them into the global namespace. If you look at the Components.utils.import documentation, you see that you can import onto a specific scope. That is, you don't have to pollute the global namespace at all.
You can collect your modules into a myExtension namespace.
var myExtension = {};
Components.utils.import("resource://.../module.jsm", myExtension);
And wrapping this inside a self-executing function doesn't let any variables leak into the global namespace, not even myExtension!
(function(){
var myExtension = {};
Components.utils.import("resource://.../module.jsm", myExtension);
})();
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?
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
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
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"
I know that global variables are bad.
But if I am using node's module "util" in 40 files in my framework, isn't it better to just declare it as a global variable like:
util = require('util');
in the index.js file instead of writing that line in 40 files?
Cause I often use the same 5-10 modules in each file, that would save a lot of time instead of copy paste all the time.
Isn't DRY good in this case?
You could just have a common module.
common.js:
Common = {
util: require('util'),
fs: require('fs'),
path: require('path')
};
module.exports = Common;
app.js:
var Common = require('./common.js');
console.log(Common.util.inspect(Common));
Each module is supposed to be independent. The require doesn't cost anything anyways after the first one for each module.
What if you wanted to test one module alone? You'd be having a lot of issues because it wouldn't recognize some "global" requires that you have in your app.
Yes, globals are bad, even in this case. Globals almost always ruin: testability, encapsulation and ease of maintenance.
Updated answer Jan. 2012
The global object is now a global inside each module. So every time you assign to a global variable (no scope) inside a module, that becomes part of the global object of that module.
The global object is therefore still not global, and cannot be used as such.
Updated Dec. 2012
The global object now has the global scope within the application and can be used to store any data/functions that need to be accessed from all modules.
global.util = require('util');
There's a section about global objects in the node documentation.
However, globals should be used with care. By adding modules to the global space you reduce testability and encapsulation. But there are cases where using this method is acceptable. For example, I add functions and objects to the global namespace to use within my unit test scripts.
I'm confused by the answers in this thread.
I am able to do this...
File: test.js
global.mytest = {
x: 3,
y: function() { console.log('Works.'); }
};
File: test2.js
console.log('Does this work?');
mytest.y();
File: server.js
require('test.js');
require('test2.js');
And it seems to work as the question needed. The first require places the mytest object into the global scope, then the second require can access that object without any other qualifiers.
I was trying to figure this out (which brought me to this thread from a Google search) and I wanted to post what seems to work for me now. Maybe things have changed since the original answers.
I have successfully been using the process object for passing around my configuration object. While in theory suffering from the exact same issues as mentioned above (encapsulation, testability and so forth) it works fine when using only non-state modifying properties (a hash table with primitives, basically).
If you wrap your modules in blocks (e.g. anon functions) you can bind to a local name (via parameter or 'var') and then have any arbitrary long (perhaps "package" labeled) name you want (if you even need a global at this point).
For instance, my modules often look similar to:
;(function ($, $exp, other) {
$(...)
other.xyz()
$exp.MyExportedObject = ...;
})(jQuery, window, some_module.other_expression) // end module
I use jQuery with noConflict, this the former, and the latter show you can do this for any expression -- global, require, computed, in-line, whatever... this same "wrapping" approach can be used to eliminate all (or almost all) "special named" globals -- globals must exist at some level, however, removing potentially conflicts is a very big win.