Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

The main reason why I ask this question is because I hear about a lot of outdated JS techniques that are no good any more or just outdated. Seeing threads from '08 scares me after hearing all the negativity about older JS.

My main concerns are variables and files.

I want to create some kind of advanced calculator for a video game so I will have TONS of variables that need to be global. Since characters in the game have so many different 'stats', is it better to do something like this even if it means more writing, well just a prefix before everything:

stats.health = 50;
stats.mana = 50;
stats.whatever = 100;

//or is this better:

health = 50;
mana = 50;
whatever = 100;

Next question is about the files. I will have quite a few arrays with tons of data, lots of images loaded and lots of onTouch functions for the images. Do I create seperate JS files for each? First load all the data, then the images and then the functions and at the very bottom before the /html or /body tag add the listeners? I come from Lua, although I've known html + css from before, I'm just starting out in JS so any advices is greatly appreciated.

Another thing that I'm not sure of is, I've seen at least 3 methods of creating images, what's the difference between them?

For example:

for (var i = 0; i < imageSrc.length; i++) {
image[i] = new Image(); 
image[i].src = "images/" + imageSrc[i] + ".png"; 
end

also:

document.createElement("img");

That's using javascript to create images while the user is using the page.

Is there a better way to create images that will exist right from the beginning? For example creating this within a div:

<img id="bgMain" src="images/background.png" style="position:absolute; top:0px; left:0px;" />

My last question is: http://jsperf.com/cached-vs-getelementbyid/5

The performance for cache is obviously way better, but I don't understand what obj.elems.el is at all or if I look into it. Does anyone have a link to proper explaining on how to cache variables?

Also any extra info and tips on better coding practices is greatly appreciated. Thanks so much for reading and thanks in advance for any help!

share|improve this question
For the record, there is exactly the same chance of collision with a "namespace" object as there is with plain identifiers using similar characters, e.g. "myLib.foo" and "myLib_foo" are equally safe (or unsafe, depending on your point of view). Eventually you must make something global, unless your entire program runs in an immediately invoked function expression (IIFE), which seems unlikely for a game. – RobG 9 hours ago

3 Answers

up vote 1 down vote accepted

I will have TONS of variables that need to be global

Why do they need to be global? Seeing by your data, you are doing some character stats calculator. I suggest you learn OOP in JavaScript and build your character models based on objects. That way, they are "instances of characters" and not globals. I would looks something like:

//build a character
var character = new Character('XXXfoozballXXX');
character.health = 100;
character.mana = 100;
character.simulateHit();
character.setStats({
  str:120,
  agi:120,
  luk:90,
  ...
});

//The data never lives in the global. They are in the instances of objects.
//You can discard them and build new ones without worry of globals or resetting

I will have quite a few arrays with tons of data, lots of images loaded and lots of onTouch functions for the images. Do I create seperate JS files for each?

You need some dependency handling framework, and structure. I suggest you learn RequireJS and Backbone for starters. There are other frameworks out there, they just happen to be what I use at the moment.

RequireJS will require you to split the files for modularity and reusability, but will compile them with their optimizer into one file. Backbone provides a way for you to split your data, your UI and your logic into objects as well, making it important you learn OOP first.

Another thing that I'm not sure of is, I've seen at least 3 methods of creating images, what's the difference between them?

There are a lot of ways of doing it:

  • Building the element in JavaScript
  • Building an Image object in JavaScript
  • Build the HTML and use .innerHTML()

I prefer the second method, since it's OOP-like which will be much easier to handle with other OOP-like code.

The performance for cache is obviously way better, but I don't understand what obj.elems.el is at all or if I look into it. Does anyone have a link to proper explaining on how to cache variables?

What the cached method did was to get the element from the DOM only once as well as reducing the entire test into assignments rather than binding, fetching etc. JavaScript and the DOM are "separate worlds", so to speak. Crossing code from one "land" to the other entails overhead.

To avoid that overhead, you limit the "crossings". Since you already fetched the element once, and have reference of it now, you need not fetch it again. Instead, reuse already existing references.

share|improve this answer
Wow, thank you for the 'new Character' info, that looks really promising. Would you say it's better if I create 50-100 of those? Or have lets say 5 arrays with 50-100 elements in each array and when the user selects a different person just the single character takes on new values from the other arrays? Thanks a lot for the framework's as well, will definitely look into both of them and OOP. Thank you so much for taking the time to write all that out and explaining it, very much appreciated – Hate Names 9 hours ago
1  
Objects and Arrays in JS have a similar overhead, it depends on the prototype chain, and the number of properties on those prototypes as to the impact. As far as code organization, structuring your code into usable structures is probably more beneficial, generally speaking your DOM/Canvas updates are going to be the most resource intensive. – Tracker1 9 hours ago
Hey again, sorry for the delay on the response, I have one last question. So there are items I have to input too, not only characters. Let's say there are 200 items, each with 15 properties. Would it be better to create 15 arrays with 200 properties or 200 characters each with 15 properties? Thanks once again for all your help – Hate Names 7 hours ago
1  
@HateNames Think of objects like "real objects". Here's an analogy: You have people with names, not names that have people. – Joseph the Dreamer 6 hours ago
I get the analogy but I don't get which ones better for performance =( Thanks for all your help tho I'll just stick to reading more for now. Using OOP just saves the time and code from writing? From what I can tell doing function Character(agi,str,luk) { this.agi = agi, this.str = str etc } and then MainDude = new Character(120, 120, 90) just saves me from writing all the properties? Cuz for spell damage I might end up writing over 50 prop. For SecondDude = new Character( 1, 2, 3, 4...50 ) wouldnt make much sense when you read. Or am I not getting the way it works? – Hate Names 6 hours ago
show 2 more comments

The biggest arguments against previous JS exploits have been tons of global variables and the increased potential for collisions... the simplest way around this has historically been namespacing...

//"this" is the global namespace, window in a browser.
this.project = this.project || {}; //establish project namespace
project.section = project.section || {}; // project.section
project.section.somevar = 0;
project.section.someMethod = function(){
  ...
};

This has it's ups and down sides, the upside is you get structure, and can avoid collisions... the down side is that this practice takes a lot of discipline to minimize leaky abstractions. Also, the cost of tree searching for project.section.subsection.area.method has a bit of a lookup cost.

You can reduce leaky abstractions (accidental variable leaks) by wrapping your code files in Immediately Invoked Function Expressions (IIFE)

(function(){
  this.project = this.project || {};
  //
}());

Even then, there is still a lot of work involved in maintaining such a codebase. More recently there has been a growth in module patters for JavaScript. You will probably want to think in terms of modules, and working with those modules and objects/classes they expose. Currently there are two popular patterns for this, which are Asynchronous Module Design (AMD) and CommonJS (CJS) there are also many different tools for building your modules into scripts that can be used client side.

You will most likely want to use RequireJS (AMD), and look into Bower (JS Package Manager), Grunt and Yeoman.

There are quite a few tutorials available for this, and you may want to look into a toolkit like FrozenJS, at least for structure examples.

Following is an example of how you might structure a module for your system... said module would be for a given Character on the field that inherits from field module's Entity... You would expose a constructor 'Character' that has a bind(field) method, and a render() method... to handle its' own state. You could think of this as a character controller or ViewModel (in MVC/MVVM terms).

//character.js AMD Module
define(['jQuery','./field'],function($,fieldModule){
  //module
  return {
    'Character':CharacterObject
    ...
  };

  function CharacterObject() {
    ... constructor internals ...
  }

  //inherit from field.Entity
  CharacterObject.prototype = new fieldModule.Entity();

  //prototype methods
  CharacterObject.prototype.bind = function(fieldInstance) {
    ... bind the CharacterObject instance to the field ...
  }

  CharacterObject.prototype.render = function() {
    ... render UI update(s) ...
    //assuming an event loop for UI processing
  }

  ...
});

Beyond all of this, you may want to even consider coffee-script which reduces the chance of certain behavioral issues even farther, at the cost of a middle-man language/compilation step that you may not find worthwhile.

share|improve this answer
Wow thank you so much for taking the time to explain all of this. I will definitely be looking into everything you posted and linked about. I have a quick question though, tons of global variables = possible variable leaks? What does that mean exactly? I did not even know variables could 'leak'. Does it mean possibly it doesn't find it or it gets a different variable and my entire function messes up completely? Thanks once again for taking the time to read and reply! Greatly appreciated. – Hate Names 9 hours ago
1  
"Namespacing" doesn't help with collisions any more than prefixing globals does (e.g. myLib. vs myLib_), it does make things tidier though. – RobG 9 hours ago
1  
@RobG if, instead of "project" above, you use "mycompany.site/projectname..." it reduces the chance of conflicting with "random library" a lot. It reduces risk, but doesn't eliminate it. – Tracker1 9 hours ago
@Tracker1—yes, the more characters in the identifier, the less chance of a collision. – RobG 5 hours ago

There is really no good argument for having many global variables. Make a single global container, and stick everything inside of it.

window.globalContainer = {};
globalContainer.var1 = 1;
globalContainer.var2 = 2;
//etc

More than likely you will realize that it is possible to not even use a globalContainer as you can have everything run in a scoped environment where entry is dictated by events.

Every file which houses .js must be fetched. The fetching is slow, so you should just try to do it once instead of multiple times. Combine all the script you can into one file instead of having them all over the place. That being said, you should only do that for production - when developing you should do what is most readable. Keep in mind that your production and development javascript should always be different. One which is easy to read and logically separated, and one which is easy to transfer, and minified.

The route you take to load an image does not really matter. createImage or new Image() will both have the same results. The important thing to remember is that the actual image is not fetched until .src has been assigned. When that happens, the image is loaded. Once a browser sees a resource it caches it. So that is how the preloading magic happens. Rendering is a whole other beast. Even if you have cached an image it may take some time to render, especially if there are many of them set to render at once and they are large images.

share|improve this answer
Thank you very much for taking the time to explain it. Is there no limit to how big a js file can be? Would you suggest the same thing to a file with 500k-1mil characters written? Is that even feasible for a web page? I wouldnt mind too much since I figured I could use things like google chromes packaged apps. Thanks once again for all the info – Hate Names 9 hours ago
1  
@HateNames - No limit to the file size aside from what the disk can handle, and how long you are willing to allow your user to wait. More than likely you can make your code more efficient than 1 million characters. The more you write, the better you will get at reducing coding redundancy :) – Travis J 9 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.