this is my current code
function includeClass(classname, ctx) {
var txt = fs.readFileSync("socket.io/" + classname + ".js");
return txt;
}
//define globals here
var _PLAYERS = {};
var _SPAWNPOINTS = [];
vm.runInThisContext(includeClass("vector"));
vm.runInThisContext(includeClass("class"));
vm.runInThisContext(includeClass("connectionHandler"));
vm.runInThisContext(includeClass("game"));
But that way, class.js file can't access variables from global scope or other files. because now i get errors like, _PLAYERS or require is undefined. I've tried eval() too, but it didn't do anything at all.
How can I run these js scripts in main script so they get interpreted as 1 whole?
https://nodejs.org/api/vm.html#vm_vm_runinthiscontext_code_options:
Running code does not have access to local scope, but does have access to the current global object.
Your _PLAYERS variable is not truly global, it is local to your script. As well as some other variables (like require) which are also in the module scope.
You can try to assign the needed variables to global object, however, I am not well aware what side effects and complications may follow.
Related
This is most likely a very simple one.
I have created a game in canvas and js. However I stumbled upon a problem. As I can access the variables and code inside the chrome console, I can change f.ex. the player score to whatever I'd like. This is not very good.
Is there some way I can make the file and variables non accessible through the console for players to use?
Thanks!
You can put the whole script into an IIFE so that any variables declared will be scoped to the just-invoked function, rather than be on the top level and accessible anywhere. For example:
(function() {
var playerName = 'bob';
var turnCount = 1;
// do stuff with playerName and turnCount,
// they won't be accessible or changeable from the outside
// you can declare functions and such here as well
// which will also only be accessible from the inside
})();
Like this, referencing playerName from the console will fail.
you can use a proxy.
javascript proxy
or you can make an IIFE and expose only the required functions such as:
var App = (function() {
var test = '';
var init = function() {
App.test = 'test';
};
return {
init: init
};
})();
or define your properties as not writable with Object.defineProperty()
In browser, diffrent javascript file share one scope:
a.js:
var a=1; //we add "var", so we not intent it be a global var.
b.js:
console.log(a) //a=1, but b.js can also see this var!
In nodejs:
a.js ....
b.js ....
console.log(a)// b.js cannot see the var, declare by "var" keywork
is there any doc say those difference ?
that is correct. All of the files are loaded in the browser combined but in node.js uses modules per file so basically to combine the files from b.js you need to do
var a=require('a.js');
then your variable will be in a.a
for this to work you need to exports.a=1 in a.js
Be sure to keep in your mind that while javascript is the same language, different programming techniques are used in frontend and backend.
nodejs encapsulates scope per file, sort of like ruby. If you want to share variables you should export them:
file1.js:
exports.a = 5;
file2.js:
exports.b = 6;
main.js:
var file1 = require('./file1.js');
var file2 = require('./file2.js');
console.log(file1.a); // 5
console.log(file2.b); // 6
Anything you export in a file by assigning to export.variablename = yourObject; will be accessible when you include the file from elsewhere: var exportedStuff = require('./file.js') would let you access yourObject at exportedStuff.variablename.
The reason for all of this is to force you to be more organized about how you write your code. As opposed to just slapping global variables around everywhere, it forces you to organize your code into modules, and also gives you the ability to emulate private scoping in an easier way than on the web.
In the web when you omit var, and just have varname = 5 then when variable does not already exist, it's the same as saying window.varname. This is NOT the case in nodejs. In Node if you want to use global you must do global.varname = 5
Hello I am new JavaScript unit testing and I'm using Mocha.js and Chai.js
What I want to do is simply figure out how to check the value of a global variable in a seperate js file. Here is my code
Here is the main.js file (code to be tested) Just has the variable I want to test against.
//main.js
var foo = 9;
Here is my test file
var assert = require("assert")
var expect = require('chai').expect
var fs = require("fs")
var vm = require("vm")
function include(path){
var code = fs.readFileSync(path,'utf-8');
vm.runInThisContext(code,path);
}
describe('Global', function(){
include('lib/main.js');
it('Should check if value is matching', function(){
expect(foo).to.equal(9);
});
});
Again, I'm new to unit testing in JavaScript. Any help will be greatly appreciated. The error I get back is foo is not defined which tells me that it can't access the variable, so how can I access it? Thank you in advance for the help.
var foo = 9; does not declare a global variable, it declares a local variable. In Node.js, a local variable declared in the outermost scope of a module will be local to that module.
If you want to test the value of a local variable declared in another file, your best bet is probably to read the contents of that file into a string (using fs.readFileSync, perhaps) and then eval() the string, which should define the variable in the current scope.
That will only work if the local variable is declared in the file's outermost scope. If it's a local variable inside a function, for example, you're out of luck (unless you want to do some gnarly string parsing, which would stretch the bounds of sanity).
Your global object is usually window
a global var foo = "test"; is the same as window.foo = "test"; or window['foo'] = "test";
Window is not defined when mocha is run in node, but this blog post uses "this" combined with a self-invoking function to get the same result.
I need a few global variables that I need in all .js files.
For example, consider the following 4 files:
global.js
js1.js
js2.js
js3.js
Is there a way that I can declare 3 global variables in global.js and access them in any of the other 3 .js files considering I load all the above 4 files into a HTML document?
Can someone please tell me if this is possible or is there a work around to achieve this?
Just define your variables in global.js outside a function scope:
// global.js
var global1 = "I'm a global!";
var global2 = "So am I!";
// other js-file
function testGlobal () {
alert(global1);
}
To make sure that this works you have to include/link to global.js before you try to access any variables defined in that file:
<html>
<head>
<!-- Include global.js first -->
<script src="/YOUR_PATH/global.js" type="text/javascript"></script>
<!-- Now we can reference variables, objects, functions etc.
defined in global.js -->
<script src="/YOUR_PATH/otherJsFile.js" type="text/javascript"></script>
</head>
[...]
</html>
You could, of course, link in the script tags just before the closing <body>-tag if you do not want the load of js-files to interrupt the initial page load.
The recommended approach is:
window.greeting = "Hello World!"
You can then access it within any function:
function foo() {
alert(greeting); // Hello World!
alert(window["greeting"]); // Hello World!
alert(window.greeting); // Hello World! (recommended)
}
This approach is preferred for two reasons.
The intent is explicit. The use of the var keyword can easily lead to declaring global vars that were intended to be local or vice versa. This sort of variable scoping is a point of confusion for a lot of Javascript developers. So as a general rule, I make sure all variable declarations are preceded with the keyword var or the prefix window.
You standardize this syntax for reading the variables this way as well which means that a locally scoped var doesn't clobber the global var or vice versa. For example what happens here is ambiguous:
greeting = "Aloha";
function foo() {
greeting = "Hello"; // overrides global!
}
function bar(greeting) {
alert(greeting);
}
foo();
bar("Howdy"); // does it alert "Hello" or "Howdy" ?
However, this is much cleaner and less error prone (you don't really need to remember all the variable scoping rules):
function foo() {
window.greeting = "Hello";
}
function bar(greeting) {
alert(greeting);
}
foo();
bar("Howdy"); // alerts "Howdy"
Have you tried it?
If you do:
var HI = 'Hello World';
In global.js. And then do:
alert(HI);
In js1.js it will alert it fine. You just have to include global.js prior to the rest in the HTML document.
The only catch is that you have to declare it in the window's scope (not inside any functions).
You could just nix the var part and create them that way, but it's not good practice.
As mentioned above, there are issues with using the top-most scope in your script file. Here is another issue: The script file might be run from a context that is not the global context in some run-time environment.
It has been proposed to assign the global to window directly. But that is also run-time dependent and does not work in Node etc. It goes to show that portable global variable management needs some careful consideration and extra effort. Maybe they will fix it in future ECMS versions!
For now, I would recommend something like this to support proper global management for all run-time environments:
/**
* Exports the given object into the global context.
*/
var exportGlobal = function(name, object) {
if (typeof(global) !== "undefined") {
// Node.js
global[name] = object;
}
else if (typeof(window) !== "undefined") {
// JS with GUI (usually browser)
window[name] = object;
}
else {
throw new Error("Unkown run-time environment. Currently only browsers and Node.js are supported.");
}
};
// export exportGlobal itself
exportGlobal("exportGlobal", exportGlobal);
// create a new global namespace
exportGlobal("someothernamespace", {});
It's a bit more typing, but it makes your global variable management future-proof.
Disclaimer: Part of this idea came to me when looking at previous versions of stacktrace.js.
I reckon, one can also use Webpack or other tools to get more reliable and less hackish detection of the run-time environment.
Yes you can access them. You should declare them in 'public space' (outside any functions) as:
var globalvar1 = 'value';
You can access them later on, also in other files.
listofLOBs: function(data) { //passing data
var returnLOB = [];
console.log(data);
for (var i1r= 0; i1r < data.length; i1r++) {
var lob = new LOBslist();
lob.name = data[i1r].name;
lob.id = data[i1r].id;
returnLOB.push(lob); // storing in returnLOB
}
console.log(returnLOB[1].name);
$('#mainWrapper').find('select[name="lob-select"] option:selected').text(returnLOB[1].id); //using the returnLOB's object data to populate dropdown
return returnLOB;
}
In the above function i am storing objects in the returnLOB array and using it inside the function itself to populate a dropdown.
But say this is file1.js, i would like to access returnLOB's values from file2.js How can i do that? Thanks in advance.
Note: i have declared returnLOB[] globally too.(outside the above function)
To do what you want, you just need to remove var from your function so that you're not creating a local variable that shadows the global variable you've created in another file.
listofLOBs: function(data) {
// Here you're setting a global instead of a local
returnLOB = [];
You probably know this is a bad idea, and it would be better if you restructure your code so that you don't need a global
A simple solution is to have all code that needs the variable in one place with a self-executing function so your global is only exposed to the code that needs it
(function(){
var returnLob;
... contents of file 1, which write to returnLob
... contents of file 1, which read returnLob
})()
As long as you include file1.js before file2.js, it will work. Take jQuery as an example - or any JS library for that matter - if you include its source file before your code, you can use functions within it.
You want to include the files in the above order, then you can just call the function (listofLOBs()) in file 2.
Additionally, your variable declaration within the function is incorrect.
var returnLOB = []; // You're declaring a global.
should be
returnLOB = []; // because the variable is already declared - you just want a local copy.
Hope this helps.
You should be able to access any globals between files. In your example you defined returnLOB inside of a function so that won't be accessible but the one you claimed to have defined globally will be accessible by both files.
This also has been asked before so check out:
Javascript: Scope of a Variable across different Javascript files