I asked here:
node.js require inheritance?
and was told that I can set variables to the global scope by leaving out the var.
This does not work for me.
ie:
_ = require(\'underscore\');
Does not make the _ available on required files. I can set with express\'s app.set
and have it available elsewhere though.
Can somebody confirm that this is supposed to work? Thanks.
In node, you can set global variables via the \"global\" or \"GLOBAL\" object:
GLOBAL._ = require(\'underscore\'); // but you \"shouldn\'t\" do this! (see note below)
or more usefully...
GLOBAL.window = GLOBAL; // like in the browser
From the node source, you can see that these are aliased to each other:
node-v0.6.6/src/node.js:
28: global = this;
128: global.GLOBAL = global;
In the code above, \"this\" is the global context. With the commonJS module system (which node uses), the \"this\" object inside of a module (ie, \"your code\") is NOT the global context. For proof of this, see below where I spew the \"this\" object and then the giant \"GLOBAL\" object.
console.log(\"\\nTHIS:\");
console.log(this);
console.log(\"\\nGLOBAL:\");
console.log(global);
/* outputs ...
THIS:
{}
GLOBAL:
{ ArrayBuffer: [Function: ArrayBuffer],
Int8Array: { [Function] BYTES_PER_ELEMENT: 1 },
Uint8Array: { [Function] BYTES_PER_ELEMENT: 1 },
Int16Array: { [Function] BYTES_PER_ELEMENT: 2 },
Uint16Array: { [Function] BYTES_PER_ELEMENT: 2 },
Int32Array: { [Function] BYTES_PER_ELEMENT: 4 },
Uint32Array: { [Function] BYTES_PER_ELEMENT: 4 },
Float32Array: { [Function] BYTES_PER_ELEMENT: 4 },
Float64Array: { [Function] BYTES_PER_ELEMENT: 8 },
DataView: [Function: DataView],
global: [Circular],
process:
{ EventEmitter: [Function: EventEmitter],
title: \'node\',
assert: [Function],
version: \'v0.6.5\',
_tickCallback: [Function],
moduleLoadList:
[ \'Binding evals\',
\'Binding natives\',
\'NativeModule events\',
\'NativeModule buffer\',
\'Binding buffer\',
\'NativeModule assert\',
\'NativeModule util\',
\'NativeModule path\',
\'NativeModule module\',
\'NativeModule fs\',
\'Binding fs\',
\'Binding constants\',
\'NativeModule stream\',
\'NativeModule console\',
\'Binding tty_wrap\',
\'NativeModule tty\',
\'NativeModule net\',
\'NativeModule timers\',
\'Binding timer_wrap\',
\'NativeModule _linklist\' ],
versions:
{ node: \'0.6.5\',
v8: \'3.6.6.11\',
ares: \'1.7.5-DEV\',
uv: \'0.6\',
openssl: \'0.9.8n\' },
nextTick: [Function],
stdout: [Getter],
arch: \'x64\',
stderr: [Getter],
platform: \'darwin\',
argv: [ \'node\', \'/workspace/zd/zgap/darwin-js/index.js\' ],
stdin: [Getter],
env:
{ TERM_PROGRAM: \'iTerm.app\',
\'COM_GOOGLE_CHROME_FRAMEWORK_SERVICE_PROCESS/USERS/DDOPSON/LIBRARY/APPLICATION_SUPPORT/GOOGLE/CHROME_SOCKET\': \'/tmp/launch-nNl1vo/ServiceProcessSocket\',
TERM: \'xterm\',
SHELL: \'/bin/bash\',
TMPDIR: \'/var/folders/2h/2hQmtmXlFT4yVGtr5DBpdl9LAiQ/-Tmp-/\',
Apple_PubSub_Socket_Render: \'/tmp/launch-9Ga0PT/Render\',
USER: \'ddopson\',
COMMAND_MODE: \'unix2003\',
SSH_AUTH_SOCK: \'/tmp/launch-sD905b/Listeners\',
__CF_USER_TEXT_ENCODING: \'0x12D732E7:0:0\',
PATH: \'/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:~/bin:/usr/X11/bin\',
PWD: \'/workspace/zd/zgap/darwin-js\',
LANG: \'en_US.UTF-8\',
ITERM_PROFILE: \'Default\',
SHLVL: \'1\',
COLORFGBG: \'7;0\',
HOME: \'/Users/ddopson\',
ITERM_SESSION_ID: \'w0t0p0\',
LOGNAME: \'ddopson\',
DISPLAY: \'/tmp/launch-l9RQXI/org.x:0\',
OLDPWD: \'/workspace/zd/zgap/darwin-js/external\',
_: \'./index.js\' },
openStdin: [Function],
exit: [Function],
pid: 10321,
features:
{ debug: false,
uv: true,
ipv6: true,
tls_npn: false,
tls_sni: true,
tls: true },
kill: [Function],
execPath: \'/usr/local/bin/node\',
addListener: [Function],
_needTickCallback: [Function],
on: [Function],
removeListener: [Function],
reallyExit: [Function],
chdir: [Function],
debug: [Function],
error: [Function],
cwd: [Function],
watchFile: [Function],
umask: [Function],
getuid: [Function],
unwatchFile: [Function],
mixin: [Function],
setuid: [Function],
setgid: [Function],
createChildProcess: [Function],
getgid: [Function],
inherits: [Function],
_kill: [Function],
_byteLength: [Function],
mainModule:
{ id: \'.\',
exports: {},
parent: null,
filename: \'/workspace/zd/zgap/darwin-js/index.js\',
loaded: false,
exited: false,
children: [],
paths: [Object] },
_debugProcess: [Function],
dlopen: [Function],
uptime: [Function],
memoryUsage: [Function],
uvCounters: [Function],
binding: [Function] },
GLOBAL: [Circular],
root: [Circular],
Buffer:
{ [Function: Buffer]
poolSize: 8192,
isBuffer: [Function: isBuffer],
byteLength: [Function],
_charsWritten: 8 },
setTimeout: [Function],
setInterval: [Function],
clearTimeout: [Function],
clearInterval: [Function],
console: [Getter],
window: [Circular],
navigator: {} }
*/
** Note: regarding setting \"GLOBAL._\", in general you should just do var _ = require(\'underscore\');
. Yes, you do that in every single file that uses underscore, just like how in Java you do import com.foo.bar;
. This makes it easier to figure out what your code is doing because the linkages between files are \'explicit\'. Mildly annoying, but a good thing. .... That\'s the preaching.
There is an exception to every rule. I have had precisely exactly ONE instance where I needed to set \"GLOBAL._\". I was creating a system for defining \"config\" files which were basically JSON, but were \"written in JS\" to allow a bit more flexibility. Such config files had no \'require\' statements, but I wanted them to have access to underscore (the ENTIRE system was predicated on underscore and underscore templates), so before evaluating the \"config\", I would set \"GLOBAL._\". So yeah, for every rule, there\'s an exception somewhere. But you had better have a darn good reason and not just \"i get tired of typing \'require\' so I want to break with convention\".
The other solutions that use the GLOBAL keyword are a nightmare to maintain/readability (+namespace pollution and bugs) when the project gets bigger. I\'ve seen this mistake many times and had the hassle of fixing it.
Use a JS file then use module exports.
Example:
globals.js
var Globals = {
\'domain\':\'www.MrGlobal.com\';
}
module.exports = Globals;
Then if you want to use these, use require.
var globals = require(\'globals\'); //<< globals.js path
globals.domain //<< Domain.
global._ = require(\'underscore\');
Note that using GLOBAL
is deprecated:
(node:59502) DeprecationWarning: \'GLOBAL\' is deprecated, use \'global\'
My comment:
If you know what you\'re doing, I think its OK to use global. When I\'d have to require some library every time I want to use it (and let\'s say I\'m using it in tens or hundreds of files) I think it destroys the main point of a lot of libraries that are made to be easy and quick to use. Why is it named _
, not amazingLibraryCalledUnderscore
?
So for me, needing to write 30 chars of var _ = require(\'underscore\');
is 3000%
more than required minimum (1 char). Yes. I\'m obsessed about making my life easier when writing the code. I just hate repeating obvious things. If I once told damn node what I mean by I want you to know _ means I use underscore
I don\'t want to say it again.
So - I believe when you control your code, you should try to make it sexy. I believe writing 30 chars every time to do so simple thing is damn ugly!
ps. to trust yourself when you say I control my code
, you need to have experience of loosing this control at least once.
What about a global namespace like global.MYAPI = {}
global.MYAPI._ = require(\'underscore\')
Edit after camilo-martin\'s comment: All other posters talk about the bad pattern involved. So leaving that discussion aside, the best way to have a variable defined globally (OP\'s question) is through namespaces.
@tip: http://thanpol.as/javascript/development-using-namespaces/
I agree that using the global/GLOBAL namespace for setting anything global is bad practice and don\'t use it at all in theory (in theory being the operative word). However (yes, the operative) I do use it for setting custom Error classes:
// Some global/config file that gets called in initialisation
global.MyError = [Function of MyError];
Yes, taboo here, but if your site/project uses custom errors throughout the place, you would basically need to define it everywhere, or atleast somewhere to:
- Define the Error class in the first place
- In the script where you\'re throwing it
- In the script where you\'re catching it
Defining my custom errors in the global namespace saves me the hassle of require\'ing my customer error library. Imaging throwing a custom error where that custom error is undefined.
Also too, if this is wrong then please let me know as I\'ve only just started doing this recently