An strucure to share data between scopes - javascript

I am just learning JS and try to write a simple game. So I made a basic structure witch should look something like this (pseudo c++ code):
if (!game.game-stage)
game.ResetGame(); // initialize game objects
if (player1.score > MAX_SCORE || player2.score > MAX_SCORE)
game.end-round(); stop(1000);
else
game.Update();
game.Render();
Then I try to write it in JS:
function main() {
if (gamest != true) {
resetgame();
gamest = true;
}
/* UPDATE SECTION */
if (score1 > 9 || score2 > 9) {
endround();
setTimeOut(update, 1000);
}
else {
update();
}
/* RENDER SECTION */
draw();
}
Other functions in main() does now have access to objects initialized in resetgame() function. The other problem that appears is that setTimeOut(update, 1000) does not work, when I did put all object to global scope for testing.
resetgame() procedure looks pretty much like this:
function resetgame() {
var paddle1 = new GameObject(20, 80, "LEFT");
[...]
Does that structure makes any sens?

The problem
function main() {
if (gamest != true) {
resetgame();
gamest = true;
}
The resetgame() function is bound inside an if scope. It cause the objects initialized inside this scope to be destroyed after program leaves that scope.
Closure solution
To get use of closure concept we need:
variable
body of logic that variable is bound to
environment that is saved during the closure's instantiation, this is for free variables that exist within the body to be bound when the closure variable is evaluated.
So in this example, we would need a bunch of free object inside the function main() body to save data evaluated by resetgame(). One option will be to pass all those object by arguments to the resetgame() and rewrite it to initialize all arguments to its inner objects.
Simple OOP solution
In a game we usually have a lot of objects, so the closure concept will get to complex and memory consuming. The better solution will be to encapsulate all main functions in to one object so we can easy exchange data and pass the object where-ever we need. That let us create an easy to menage structure, e.g.:
var App = {
Load: function() {
this.frame = new Frame();
},
// UPDATE
Update: function() {
this.frame.updatePosition();
},
// RENDER
Render: function() {
this.frame.draw();
}
};
function Main() {
var app = App;
app.Load();
setInterval(MainLoop(app), 1000/60);
}
function MainLoop(app) {
// main application render
app.Render();
// main application update
app.Update();
}
Someone just remind me about thus question. I'm not a JS expert yet but for that application I find my solution. I know that could be solved better but this solution is good enough for the little game I been writing. But if someone have a better one, I will be glad to hear your opinion.

Related

Function Scope in P5.js

I am using the p5.js library as the basis for my program due to its ease of implementing visual features to javascript, however I have run into a bit of trouble.
I am wanting to create multiple canvases within the same file to be displayed on an html page. I have attempted a few means of doing this and have had the most success with this means of achieving it. Effectively separating two p5 sketches via “instance mode” to then be able to reference them from separate div elements in the html file.
This means works for what I want it to. I can create x number of instances and separate them into x number of div elements on my html page without problem.
However, an integral feature of my program is that when a key is pressed it calls a function that is specific to a particular canvas. Using the keyPressed() function in p5 I am able to achieve this. However, it is not scalable to multiple canvases.
Effectively it seems that (at least with my implementation) that putting this function inside of multiple instances causes the function to only be called in the first instance and ignoring the others. To go around this I was thinking I could implement this keyPressed() function outside the scope of the instances and then have that keyPressed() function call a function from each instance to achieve what I desire.
This is where my problem has arisen, I do not know how I can refer to a function within an instance from outside the local scope of that instance. Here is some example code of what I am wanting to achieve. I am not very experienced with JavaScript and any help would be much appreciated.
function keyPressed() {
if(keyCode === [SOME_KEY]) {
//Call doSomething() from sketch1 and sketch2
}
}
//Sketch 1
var sketch1 = function( p ) { // p could be any variable name
p.setup = function() {
createCanvas(); //etc
};
p.doSomething = function() {
//etc
}
};
var myp5 = new p5(sketch1, 'c1');
// Sketch Two
var sketch2 = function( p ) {
p.setup = function() {
createCanvas(); //etc
};
p.doSomething = function() {
//etc
}
};
var myp5 = new p5(sketch2, 'c2');

JavaScript IIFE

I'll admit I'm pretty green when it comes to JavaScript and it doesn't help that every time I think I'm getting it some weird curve ball throws me right off.
I've got a js file something like this:
(function (myiife, $) {
var myArrayOfThings = [];
myiife.myFunction = function (id) {
var cachedThing = myiife.getFromArray(id);
if (cachedThing === null) {
// get from server
} else {
// do something with cached item
}
};
myiife.getFromArray = function (idToFind) {
for (var i = 0, len = myArrayOfThings; i < len; i++) {
if (myArrayOfThings[i].Id=== idToFind) {
return myArrayOfThings[i]; // Return as soon as the object is found
}
}
return null;
};
}(window.myiife= window.myiife|| {}, jQuery));
What really confuses me is the proper way to expect to be able to call things. I guess I really don't understand the scope of things yet and I'm struggling to be honest.
Is it expected that if I want to call myFunction from the page it would HAVE to look like this?
onclick="myiife.myFunction(1)"
I've read stuff on scope but I'm obviously still missing something very fundamental in my understanding of it all.
From the examples I've seen I don't see others that seem to have to prefix function names with the iife name in order to execute things from the page.
Any good recommended reading would be appreciated as well.
The global scope in Javascript (in a browser at least) is window. So what you've done is you've attached myiife to window and myiffe has a function called myFunction. So if you want to call it from the global scope (i.e. window) then, of course, you need to specify myiffe.myFunction().
What you may have seen other people do is something like this:
var myFunction = (function() {
var counter = 0;
return function() {
counter++;
console.log(counter);
};
})()
Where they have an IIFE return something (in this case a function, in many other case people will return an object). In this case, since myFunction is a global variable, they can call it with just myFunction(). What they have achieved with the IIFE is to basically make the counter variable private. Only things inside the IIFE have access to it.
Of course, if you don't define myFunction inside of an IIFE, then it will just be a function in the global scope and can be called directly from the global scope.
function myFunction() {
// do something
}
myFunction();
But to your question on using this in an event handler - better practice would be to not inline your event handler in your HTML in the first place and instead bind it in code. This gives you more flexibility, cleaner separation and more maintainable code.

Best way to combine the module pattern with closures

I'm currently trying to implement some common JS concepts
in little projects to understand better how to use them.
I've been working on a simple game, trying to
understand and use the module pattern and closures.
I'm using the module pattern from Stoyan Stefanov's 'patterns'
book.
I'm struggling to understand how best to mix modules and
closures.
I'd like to know if I'm organising the following code in a
sensible way? If so, my question is: what's the best way
to modify the code so that in the $(function(){}) I have
access to the update() function?
MYAPP.utilities = (function() {
return {
fn1: function(lives) {
//do stuff
}
}
})();
MYAPP.game = (function() {
//dependencies
utils = MYAPP.utilities
return {
startGame: function() {
//initialisation code
//game state, stored in closure
var lives = 3;
var victoryPoints = 0;
function update(){
utils.fn1(lives);
//do other stuff
}
}
}
})();
$(function(){
MYAPP.game.startGame();
//Want to do this, but it won't work
//because I don't have access to update
$('#button').on('click',MYAPP.game.update)
});
I've come up with a couple of options which would work, but
I'd like to know if they're good practice, and what the best
option is.
Options:
(1) Bind $('#button').on('click', ...) as part of the
startGame initialisation code.
(2) Assign the update() function to a variable, and
return this variable from the startGame function, So in
$(function(){}) we could have
updatefn = MYAPP.game.startGame(); and then
$('#button').on('click',MYAPP.game.update)
(3)? Is there a better way?
Thank you very much for any help,
Robin
First off, to access the update function in that fashion it will have to exposed in the returned object.
return {
update: function() {
[...]
},
startGame: function() {
[...]
this.update();
}
}
Calling obj.method() automatically sets the this reference inside this method call to obj. That is, calling MYAPP.game.startGame() sets this to MYAPP.game inside this startGame method call. More details about this behavior here.
You will also want to move the lives variable to a common scope which is accessible by both startGame and update methods, which is exactly what the closure is for:
MYAPP.game = (function() {
[...]
var lives; //private/privileged var inside the closure, only accessible by
//the returned object's function properties
return {
update: function() {
utils.fn1(lives);
},
startGame: function() {
[...]
lives = 3; //sets the closure scope's lives variable
[...]
this.update();
}
}
})();
Fiddle
In this case you will need some method to set the lives variable when you want to change it. Another way would be to make the lives variable public as well by making it a property of the returned object and accessing it through this.lives inside of the methods.
NOTE: If you simply pass a reference to the function object stored as property of the returned object as in:
$('#button').on('click', MYAPP.game.update);
The this reference inside the click handler will not point to MYAPP.game as the function reference that has been passed will be called directly from the jQuery core instead of as an object's member function call - in this case, this would point to the #button element as jQuery event handlers set the this reference to the element that triggered the handler, as you can see here.
To remedy that you can use Function.bind():
$('#button').on('click', MYAPP.game.update.bind(MYAPP.game));
Or the old function wrapper trick:
$('#button').on('click', function() {
MYAPP.game.update(); //called as method of an obj, sets `this` to MYAPP.game
});
This is important when the this keyword is used inside the update method.
There are a few issues in your code. First, update() function is not visible outside the object your creating on the fly. To make it part of game object it has to be on the same level as startGame.
Also, if you declare var lives = 3 it will be a local variable and it won't be visible outside startGame() function, as well as victoryPoints. These two variable have to be visible in some way (via closure or as object fields).
Finally, attaching MYAPP.game.update as an event listener will attach just that function, preventing you from using all other object methods/functions. Depending on what you want to do you might prefer to pass a closure like function() { MYAPP.game.update() } instead.
Your code should look something like:
MYAPP.utilities = (function() {
return {
fn1: function(lives) {
console.log(lives);
}
}
})();
MYAPP.game = (function() {
//dependencies
utils = MYAPP.utilities
var lives;
var victoryPoints;
return {
startGame: function() {
//initialisation code
//game state, stored in closure
lives = 3;
victoryPoints = 0;
},
update: function() {
utils.fn1(lives);
//do other stuff
}
}
})();
$(function(){
MYAPP.game.startGame();
//Want to do this, but it won't work
//because I don't have access to update
$('#button').on('click', MYAPP.game.update)
});
(DEMO on jsfiddle)

Global variables in Javascript (jQuery)

So this is the first time I am using Javascript in a much more powerful context, having a thick client and doing much of the heavy-lifting through javascript in itself. I am using jQuery, and a lot of the code is getting muddy at the moment coz it's all just a bunch of functions.
Turns out for some of my functions, I required variables to be passed through multiple functions with their value being maintained. The obvious way of doing this is by declaring them outside of the scope of the function and then have the function manipulate it the way it ought to . (These variables are objects and not primitive type, so I guess javascript being pass by reference, this works).
For instance, I probably have something like this
var node = //init with some value;
$(document).ready(setup);
function setup()
{
A();
B();
}
function A()
{
// operate on var node
}
function B()
{
// operate on var node
}
This is obviously a scaled down version of my code, but captures the way I deal with global variables. My question is, is there a more elegant way to do the above ?
Thanks
Any reason why you can't do:
$(document).ready(function() {
var node = //init with some value;
setup(node);
function setup(node) {
A(node);
B(node);
}
function A(node) {
// operate on var node
}
function B(node) {
// operate on var node
}
});
In general, using global variables and functions is a bad idea and should be avoided wherever possible.
Note that while you appear to have been asking specifically about node, your functions setup, A and B are also all global variables in your version.
The simplest approach would be to put all these declarations inside an anonymous function:
$(document).ready(function() {
var node = ...;
function A() {
...
}
function B() {
...
}
function setup() {
A();
B();
}
setup();
});
Only use one global variable (or as few as possible). Make any functions or objects members of your one global variable.
Douglas Crockford says
An objective measure of the quality of a JavaScript program is How
many global variables and global functions does it have? A large
number is bad because the chance of bad interactions with other
programs goes up. Ideally, an application, library, component, or
widget defines only a single global variable. That variable should be
an object which contains and is the root namespace for all of your
stuff.
Yahoo’s single global is YAHOO. It is spelled in all caps to identify
it as something special, since all lower case is ordinary and initial
caps indicates a constructor. Being in all caps, it is unlikely that
someone would use it accidentally, which further reduces the
likelihood of collision.
http://www.yuiblog.com/blog/2006/06/01/global-domination/
Also, you can create objects to further organize your code.
GLOBAL.myObject = {};
GLOBAL.myObject.myFunction = ...
I prefer the "revealing module" pattern:
var myApp = (function () {
// privates
var node;
var a = function () {
// operate on node
};
var b = function () {
// operate on node
};
// publics
var init = function () {
// initialization stuff
a();
b();
};
return {
init: init
};
})();
$(document).ready(function () {
myApp.init();
});
This way you only ever have one global, myApp, which stores everything else your app needs.
I think it makes the code harder to understand, I'd much rather take the variable in as an argument and have it as a return.
$(function(){
var outcome = multiply(add(5));
});
function add(num)
{
return num+1;
}
function multiply(num)
{
return num*5;
}
If you feel like you absolutely want to have global variables wrap your stuff in a closure so it doesn't actually go to a global scope.
ie,
(function(){
var a; // can be used in any functions within this closure, but not polluting window
function A()
{
a = 'blah';
}
})();
There are many. For instance, objects.
// jQuery shorthand for "wait till DOM ready"
$( function() {
// create node object
var node = {
id: /* some value */,
setup: function() {
this.A();
this.B();
},
A: function() {
// operate on this.id
},
B: function() {
// operate on this.id
}
};
// setup node object
node.setup();
} );
Global variables are trouble waiting to happen. Don't dirty up your global namespace. Javascript is an object oriented language, use objects. Notice your object can have a property that you can reference with the this keyword from within the objects methods.

How to conceal the functions

Hi,
I have my main file in which I include my javascript file.
In my javascript file I have this
$(document).ready(function(){
//some functions here
});
I want all the functions just available to this page and I know you can kinda conceal them to outside world of javascript by doing something like
(function(){
$document.ready(function(){
//my functions
)};
}).init();
but I am not 100% sure how would it be called or whether its even the right way.
Anyone shedding light on this would be a great help!
In javascript everything declared inside a function is only available inside that function (except for when you declare a variable without the keyword var).
So everything inside the function that you pass to $().ready() is only available inside that function.
$(document).ready(function () {
//all code here is scoped inside this function, so it can't be accessed
// outside of this function
});
Like the first comment says you can't hide them from the user, if they really want to see it, they will see it.
You can clean them up in a way if you really wanted to, something like
var mySpace = {};
mySpace.init = function() {
// your init functions here
};
in doc ready you just call
mySpace.init();
I am not sure if this is what you wanted but it is the way I understood the question
(function(){
var secret1 = function(msg) {console.log("Secret Message:" + msg);}
$document.ready(function(){
secret1("this can only be called from within");
)};
})();
secret1("this will cause a script error");
It sounds like the thing you are looking for is a 'javascript obfuscator'. Here is an example one. It makes the code much harder to read and copy. But as others have said, you can't actually fully hide javascript.
The problem here is that JavaScript is intrinsically a client-side scripting language unless using a server-side javascript application such as node.js.
As long as JavaScript is being used in this way, the entirety of your code will be downloaded much like downloading a .txt file from a website. The only real difference is that the ".js" extension and its inclusion in html <script> tags or in an AJAX call will force the user's browser to render it as JavaScript.
If you want to make the script a little harder for the user to find, however, this is doable. I recommend having your website retrieve the script via AJAX and appending it to the DOM. You can do this with require.js or by using Kickstrap and making your script into an "app." The script won't appear as a link in the DOM and the user would really have to search for it. You can make it even more difficult (without compromising the integrity of your site) by minifying the script. This will make it run faster while inadvertently making it less human-readable on the front end.
In JavaScript there is only function scope (the exception argument in try-catch being an exception). ES5 will let you use let (no pun intended) to achieve block scope but it wont be usefull untill majority of UAs implement it.
So your functions are concealed from the outside world, if with outside you mean outside the dom ready event.
$( document ).ready( function () {
var myFunc = function () {};
} );
myFunc();// <- ReferenceError: myFunc is not defined
You can't really hide the functions, as it's in the source code of a file downloaded by the client, but you can make it so they can't access your functions from javascript.
(function() {
var doStuff = function() {
// Not Accessible
console.log('You can\'t reach me!');
}
return {
'init': function() {
// Accessible
doStuff();
}
}
})().init();
If you are talking about Access Modifiers like public, private etc. Then check out this article on how Javascript handles this. Here are the key components:
//constructor function (class)
function Maths(x, y) {
//public properties
this.x =x;
this.y = y;
//public methods
this.add = function () { _sum = x + y; return _sum; }
this.mod = function () { _mod = x % y; return _mod; }
//public method calls private method
this.show = function () {
this.add();
this.mod();
showResult();
}
//private variables
var _sum=0;
var _mod=0;
//private methods
function showResult() {
alert( "sum: " + _sum + ", mod: " + _mod );
}
}
//end function
//create instance
var plus = new Maths(3, 4);
plus.show();
//static method multiply, you can use it without instance of Maths
Maths.multiply = function (x,y) { return x * y; }
//call static method by constructor function (class) without instance of Maths
var result = Maths.multiply(5,7);
alert(result);
//output: 35

Categories

Resources