Javascript file or module scope only variables - javascript

Correct me if am wrong the function require() imports the .js file somehow as copy past it in the current document so if the var name was both in two modules would the second override the first?
and how can i define file scope only variables
note that i want to define my variable outside any function in my .js file and not it be in the global scope
what are the solutions, does using the keyword var affects the variable scope, what define the scope other than function in javascript, can module object be useful for defining private variables in one file
module1.js
var name = 'i am module 1'
foo = () => console.log(name)
module.exports = foo
module2.js
var name = 'i am module 2'
foo = () => console.log(name)
module.exports = foo
main.js
const module1 = require('./module1')
const module2 = require('./module2')
module1() // "i am module 1" or "i am module 2"?
module2() // "i am module 2"

In javascript when you load the .js file directly in the '.html' file then the variables declared outside of the function get registered on global scope. To prevent this kind of things people starts using IIFE functions and wrap the single file in the IIFE. But in modern Javascript you can use modules like we used in Nodejs and module loader to load those files. Now modern browser supports ECMAScript modules and you can directly use them.
Main benefits of using modules is that you don't have to use IIFE function to prevent the variable registered on global scope. Now Every variable declared in that file are private to that file only unless you export it.
For Example:
module1.js
var name = 'my name';
function getName(){
return name;
}
module.exports = {
getName
}
In the above example name is private to this file only you can't use it in another file unless you export it.

Related

How to add value to global object from module in Node.js

I'm trying to add some value to the global or local object, but nothin happens.
I'm tried create:
global.test = {}; in main.js
And to add value test[name] = value in second js
tried create var test = {}; in second.js
And to add value test[name] = value in second js
But this examples doesn't helped me.
Code in my files:
main.js:
global.common = require('./second.js');
global.test = {}
second.js:
module.exports = {
main: function (name, value) {
test[name] = value;
}
};
second.js invoked in another files, but the whole point is displayed in the code above.
Reading the NodeJS docs:
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.
Seems like you are expecting the global scope of NodeJS to work the same way that JS works in browsers but that is not the case.
See this question for more information : What is the 'global' object in NodeJS

Javascript global variable undefined in function scope

I am new to JavaScript and trying to make a simple node server. Here is my code:
var activeGames = {}
exports.initialize = function(){
var gameID = "game12345"
activeGames.gameID = new Game(gameID, "player1", "player2")
}
I call the initialize function from another module, and I get an error stating that activeGames is undefined. activeGames is at the outermost scope of the file. I tried adding 'this' before activeGames.gameID but that did not fix it. Why is activeGames undefined? Thanks in advance.
EDIT: Here's how I'm calling this code.
In my base index file I have
const handler = require("./request-handler.js")
handler.initialize()
In request-handler.js, I have
var gameManager = require('./game-manager')
exports.initialize = function(){
gameManager.initialize()
}
JavaScript has lexical scope, not dynamic scope.
ref: https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping
Lexical scope means that whether a variable is accessible or not depends on where they appear in the source text, it doesn't depend on runtime information.
example:
function foo() {
var bar = 42;
baz();
}
function baz() {
console.log(bar); // error because bar is not in the scope of baz
}
the same problem happens in your code,
var activeGames
is not in scope.
try this variation:
exports.initialize = function(){
var activeGames = {}
var gameID = "game12345"
activeGames.gameID = new Game(gameID, "player1", "player2")
}
A good solution could be to use a class and export it:
--THIS CODE IS NOT TESTED--
class gamesManager {
var activeGames = {}
initialize() {
var gameID = "game12345"
activeGames.gameID = new Game(gameID, "player1", "player2")
}
}
exports.gamesManager = gamesManager
USE:
const activeGames = require('./game-manager');
const activeGamesInstance = new activeGames.gamesManager();
activeGamesInstance.initialize();
Need a code sample for this one. I ran this locally and it worked fine, although your code has a big issue which may be a part of your problem. It looks like you want to keep track of multiple games in activeGames. You need to use this syntax instead:
activeGames[gameID] = new Game(gameID, "player1", "player2")
Here's my working code:
index.js:
const handler = require("./request-handler");
handler.initialize('game-1234');
handler.initialize('game-5678');
request-handler.js:
var gameManager = require('./game-manager');
exports.initialize = function(gameID) {
gameManager.initialize(gameID);
}
game-manager.js:
var activeGames = {};
class Game {
constructor(id, player1, player2) {
this.id = id;
this.player1 = player1;
this.player2 = player2;
}
}
exports.initialize = function(gameID) {
activeGames[gameID] = new Game(gameID, "player1", "player2");
console.log(`game initialized! ${ Object.keys(activeGames).length } active games`);
}
Running node index results in this:
game initialized! 1 active games
game initialized! 2 active games
When you require a script file in Node.js, it is compiled as part of a function called with named parameters require, module, exports and other exposed variables as arguments1. Variables declared at file level within the required script become function level variables in the enclosing module wrapper and retained inside its closure.
Hence your "global variable" is no such thing: it's a variable defined inside a closure...
An important question then is does the module loader make variables declared in a parent module available to scripts required inside the parent. A quick test shows that the answer is general: no, modules do not have automatic access to variables declared in other modules - those variables are inside closures.
This indicates that to pass variable values to scripts that have been required, generally pass them as argument values to exported functions.
It is also possible to export any javascript value as a property of module.exports from within a required script, or add properties to an exports object after it has been returned from requiring a script. Hence it is technically feasible to pass information up and down between modules by adding properties to exports objects.
Redesigned code has multiple options to
define activeGames at the application level and pass it down as a parameter to modules needing access to it, or
export activeGames from game-manager.js by adding
exports.activeGames = activeGames
to the end of the file. This will not take care of exporting activeGames out of the parent module request-manager.js for use elsewhere, but it could be a start. Or
define activeGames as a global variable (in node) using
global.activeGames = {} // define a global object
Defining global variables is not encouraged as it can lead to collisions (and consequent program failure) between names used by applications, code libraries, future library updates and future versions of ECMAScript. Or,
Define an application namespace object for data global to the application. Require it wherever access to application data is needed:
create appdata.js as an empty file.
Optionally include a comment:
// this files exports module.exports without modification
require appdata.js wherever needed.
var appData = require('./appdata.js')
appData.gameData = {}; // for example
This relies on node.js maintaining a cache of previously required modules and does not recompile modules simply because they have been required a second time. Instead it returns the exports object of the previous require.
Happy festive season.
References
1The Node.js Way - How require() Actually Works

meaning of module.exports= function in node.js

I am taking first steps with node.js and obviously one of the first things i tried to do was exporting some data from a module, so i tried this simple case:
dummy.js:
var user = "rally";
module.exports = {
user:user
};
and than required it from a different file like this:
var dummy = require('./dummy.js');
console.log(dummy.user); // rally
So far so good, every thing works, but now i dived into code where there is this definition in the beginning of the module:
module.exports = function(passport,config, mongoose) {}
and i don't understand whats the meaning of it and how can i work with it.
just for trying to understand i defined some variables inside this abstract function but couldn't get their value from any other file.
any idea how can i export variables from module defined like this..? so for example i could require this module and get the "Dummy" variable and use it in a different file
module.exports = function(passport,config, mongoose) {
var dummy = "Dummy";
}
It works exactly the same as the first one does, only that it exports a function instead of an object.
The module that imports the module can then call that function:
var dummy = require('./dummy.js');
dummy();
any idea how can i export variables from module defined like this..?
Since functions are just objects, you can also assign properties to it:
module.exports = function(passport,config, mongoose) {}
module.exports.user = 'rally';
However I'd argue that this is less expected if a module directly exports a function. You are probably better off exporting the function as its own export:
exports.login = function(passport,config, mongoose) {}
exports.user = 'rally';
WHAT IS A MODULE?
A module encapsulates related code into a single unit of code. When creating a module, this can be interpreted as moving all related functions into a file.
// dummy.js
var exports = module.exports = {};
The utility of dummy.js increases when its encapsulated code can be utilized in other files. This is achieved by using exports.
HOW ARE THEY INVOKED?
You could declare your functions outside of the module.exports block. Functions inside exports can be invoked exactly the same way as variables or any other object.
EXAMPLE
//dummy.js
var myVariable = "foo";
var myFunction = function(){
//some logic
};
module.exports{
myVariable : myVariable,
myFunction : myFunction,
myVariableTypeTwo : "bar",
myFunctionTypeTwo : function () {
//some logic
}
}
We can now access the publicly available methods of dummy.js as a property from any js file.
var dummy = require('./dummy.js');
dummy.myVariable; //foo
dummy.myFunction();
dummy.myVariableTypeTwo; //bar
dummy.myFunctionTypeTwo();
NOTE
In the code above, we could have replaced module.exports with exports and achieved the same result. If this seems confusing, remember that exports and module.exports reference the same object.

Javascript namespacing and private modules

This is a JS newbie questions, I am working with a parent namespace Base and I include all my code within this namespace.
file model.js
Base = {}
Base.Observer = {
method1 : function(){//...},
method2 : function(){//...}
};
Base.Bot = function(name){
this.name = name;
this.somefunc = function(){};
}
file presenter.js
Base.Presenter = {
}
file helper.js
Base.Helper = { };
Now my problem is I would like to keep this module private. Without allowing any user access through any browser tools like firebug. So I could only think of wrapping them within a self executing anonymous function and making Base into a local variable which would lead to the presenter.js and helper.js not being able to access the Base namespace.
I would like to keep the files separate as it helps in keeping code organizated but I can't seem to figure what is the correct way to do this. Would appreciate any help on this.
Thank you
So I could only think of wrapping them within a self executing anonymous function and making Base into a local variable
That is the usual approach
which would lead to the presenter.js and helper.js not being able to access the Base namespace.
The function should return Base; which you then assign to a global.
See the module pattern

Obtain all functions in a file in Node.js

I have some functions inside a file. I'm trying to obtain all functions in that file, from within that file. Normally, all functions are in the window object, but I'm using Node.js, which does not seem to have a window object.
Say I have something along the lines of the following in a file:
function foo() {}
function bar() {}
then:
Are the functions saved in some global object?
If not, how can I access these functions without knowing their names? Can I iterate through all existing functions and obtain them in such a way?
The following is a common pattern
var foo = exports.foo = function() {
// ...
}
This way its written to exports and you can access it locally as foo
You want to get access to the current scope object but it's impossible in JavaScript.
Your functions are wrapped in a closure. Remember, node wraps file modules within something like this
var module = { exports: {}};
(function(module, exports){
// your file module content
})(module, module.exports);
They are locals. Assign functions to an object, exports or global to enumerate them.

Categories

Resources