What causes differences in global variables (interactive vs. scripts) - node.js

I'm running to the following issue with Node.js v0.10.1 (demonstrated with a quick example):
While running node in the interactive command line:
> global.require
{ [Function: require] . . . }
> require
{ [Function: require] . . . }
When running the following script.js I get unexpected results:
console.log(global.require); // 1.
console.log(require); // 2.
undefined // 1. `global.require` is undefined!
{ [Function: require] . . .} // 2. `require` by itself works however.
I've removed extra code denoted by .... Run it locally to see the full extent of what is actually shown.
What causes this to happen?

Node.js contains a repl module that allows you to create your own Read-Evaluate-Print-Loops (this is what repl stands for). Using this module there is a function start that you use to create a new repl.
This function takes an options object where you can configure your repl. One of these options is called useGlobal. According to the documentation for this option the following sentence is valid:
if set to true, then the repl will use the global object, instead of running scripts in a separate context. Defaults to false.
Now when you start Node.js in interactive mode, this is basically nothing but a repl like those you could create for yourself using the repl module. I guess (and please note that this is only a guess!) that Node.js's default repl has useGlobal set to true.
Hence you have a global object, which is in turn the very same as the global namespace anyway. Hence all the functions such as require that you can find on the global namespace you will again find on the global object.
Once you start a Node.js application in non-interactive mode, there is no repl, hence there is no global object.
Does that make sense to you?

Many of the Globals won't normally be in the global scope or members of the global object:
These objects are available in all modules. Some of these objects aren't actually in the global scope but in the module scope - this will be noted.
These are "globals" more by the 2nd interpretation:
Of the top-most scope.
Of an accessible scope other than the current local scope.
Also, as noted for require():
To require modules. See the Modules section. require isn't actually a global but rather local to each module.
The REPL module, that manages the interactive mode, has an option to promote them to the global scope:
useGlobal - if set to true, then the repl will use the global object, instead of running scripts in a separate context. Defaults to false.

Related

Using `window` globals in ManifestV3 service worker background script

I'm working on a Manifest v3 browser extension where I need to identify the browser in which the extension is currently running from the backgroundScript. Since ManifestV3 extension uses a service worker, it doesn't have DOM or window. So I'm not able to use window.navigator.userAgent.
I found a related question which talks about how to gets window height and width information, but I couldn't find any other information to fetch the userAgent of the browser.
Is this possible?
Neutral globals
Things like navigator aren't specific to visual representation of a window.
Just omit window. and read it directly:
navigator
navigator.userAgent
atob
fetch
Window-specific globals
Things specific to user interaction or visual/aural representation like DOM or AudioContext, or those that may show a prompt for user permissions.
Not available in a worker.
Aliases for window
Use them instead of window for code clarity or if a local variable is named just as a global property.
Built-in globalThis (Chrome/ium 71+, FF 65+) and self
These are worker-compatible aliases for the global scope. Note that a JS library you're loading may redefine them theoretically, but that'd be really weird and abnormal.
Self-made global
The most reliable method, but you'll have to add 'use strict' only inside an IIFE not globally.
This is already offered by bundlers like webpack.
Here's how you can replicate it yourself:
const global = (function(){
if (!this) throw "Don't add 'use strict' globally, use it inside IIFE/functions";
return this;
})();

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 behaviour for this keyword

Let's have a look to this very basic program.js:
console.log(this);
Here is the output:
$ nodejs program.js
{}
Now, if i do the samething in the repl console:
$ nodejs
> console.log(this)
I see a log of things at undefined at the end.
Why do we not get the same result ?
Thanks
You are experiencing two different behaviors because you're basically executing code in two different environments.
In program.js, this answer applies. You're in a node.js module, so this is the same as module.exports.
In the node.js repl, this answer applies. You're not in a node.js module; you're in the repl which uses the global context. this is the same as global. If you executed the same code in-browser, it'd reference the window object instead of global.

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

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.

Cannot set breakpoint inside function when using require inside closure

Using node-inspector, I'm unable to set breakpoint in the following node.js code. (Content of main.js)
(function() {
require('underscore');
var doSomething = function(callback) {
callback('doSomething Finished');
}
doSomething(function(x) {
console.log(x);
});
}).call(this);
I can easily set a breakpoint on line 2, line 4 or line 8, however no matter how hard I try the debugger won't let me set a break point on line 5 or line 9. To be clear, I'm using the following commands to run node-inspector
node --debug-brk main.js
node-inspector
I also tried to debug in web storm, however the issue persists. If I remove the line require('underscore');, then the problem immediately goes away and I'm able to set break point inside function body again. The problem also goes away if I remove the outermost closure function. It seems that the interaction between require and file level closure is screwing up the node debugging functionality. Has anyone experienced this problem themselves and / or knows any workarounds to be able to break inside function body?
EDIT: My node js version
Tony:~ $ node --version
v0.10.12
Tony:~ $
I ran exactly into the same issue with the same setup.
I've added a breakpoint after the definition of the target-function (that was the only place i could actually add a breakpoint). When the debugger reached that breakpoint and the function was actually defined, i was able to add breakpoints to the actual target-function...
This may not be the answer that you want to hear as it doesn't explain why you can't set any breakpoints, but I would simply remove your require statement from the closure and place it top-level. I would go even further and recommend that you don't use a closure like the one above at all.
The reason is that node uses its own module system, and unlike Javascript in the browser, declaring variables top-level does not pollute the global namespace. This is where require(...) comes in. So, you gain nothing by wrapping your code in an immediately invoked function (unless of course you want your module to be able to run both client side and server side).
I would guess that the reason that you are not able to set any breakpoints is that the V8 runtime is recognizing an unnecessary closure and then optimizing your code for you. The rewritten code may not have the correct source mapping and so breakpoints cannot be set.
So, two suggestions:
require calls are not like regular statements. They are more similar to import statements in Java and are handled specially by the compiler. They should always be top-level in a node file.
No need to wrap your code in an anonymous function when in Node.

Resources