So I have a rather large object orientated javascript class, with about 120 functions (a lot of getters and setters). Some of these functions have variables that are basically constants.
What I'm wondering, is should I declare these variables in a global scope of the object, so every time the function is run it doesn't have to re-declare the variable?
An example function is below. this.displayContacts is run several times (and will always run within the object), so in this case, there's no point declaring the 'codes' object inside the function?
function orderObject() {
this.displayContacts = function() {
var codes = {'02':'02','03':'03','07':'07','08':'08'};
// do something with codes
};
}
So, would this be better, performance wise?
function orderObject() {
var codes = {'02':'02','03':'03','07':'07','08':'08'};
this.displayContacts = function() {
// do something with codes.
};
}
My other concern is that if I end up with a lot of global variables/objects inside the main orderObject, will that be MORE of a performance hit than simply re-declaring the variables each time?
absolutely.
function MyClass() {
this.somevar = ''; // instance scoped variable
};
MyClass.CODES = {'02':'02'...}; // 'Class' scoped variable; one instance for all objects
MyClass.prototype.instanceMethod = function(){
// 'this' refers to the object *instance*
// it can still use MyClass.CODES, but can also account for variables local to the class
}
CONSTANT is 'static' so to speak, in java-talk. If your codes are global to the class (and the rest of your application), you will save a lot of overhead this way -- only define the object once. Note that you can have 'static' class-level methods as well, for those cases where the function doesn't need to operate on variables specific to an instance of the class.
Unless your app is really beefy, performance optimization probably wont make it noticeably faster. But that doesn't mean that OO design is not worth-while -- if you are going to use javascript in an object oriented way, its not too hard and never a bad idea to use good OO principals.
I would say that if you have something that you are using in multiple places that it should become a property of your object so that it doesn't have to be redeclared each time. It would also help make the maintenance of the object easier if that constant has to change. Then you are changing it only in one place and not having to hunt down all the locations where you used it.
Don't repeat yourself.
Garbage collection in JavaScript depends on the browser, and most modern browsers handle it pretty well. If you go ahead and make these global, you might see a slight performance increase simply because it's not executing that line of code every time. However, I can't imagine any significant increase in performance by making these static properties on the class, but if they don't change, then it would make more sense.
Related
Yes, this is another topic about global variables. I've searched quite a bit about them. But most of the topics is just about WHY not to use global variables and I'm convinced that I shouldn't, and I am more wondering HOW not to use them, and that I'm still unsure about.
I am working on a project, and it works wonders, but I am using about 50 global variables at the moment and that number keeps rising. Right now I've split things up in multiple .js files. Like load_chunks.js, load_images.js, render_map.js, player_actions.js, input.js, to spread the functions based on what they are for. And I've put all global variables inside settings.js.
Currently I use these global variables for these reasons:
1. Calculation based on some other global variables that doesn't change much or at all after loading. By doing this once, and store it in a global variable, I no longer have to repeat the calculation ever again. If I didn't store it in a (global) variable, Javascript would have to do the calculation many times each second, in some cases even up to few thousand times per second.
2. When the global variable is needed in many functions. Like there's this World-variable, that I use to hold data for the appearance of the world. This variable is a multidimensional array. World[y][x] for example. Load_chunks.js adds more data to this variable, or remove data if you move too far. This variable is also needed in render_map.js, to create the map, and it's also needed in player_action.js, to see if you can step on that particular location.
3. Settings; So a number in a variable that remains the same unless I change them in my script. Instead of going through my scripts, and change the numbers manually after a long search and thinking what the number was, I've put that number in 1 variable and call that variable numerous times in my scripts. These variables are in some cases also needed elsewhere.
Also I like to mention that I don't use classes, and perhaps for that reason I never got around using global variables...?
So how do I get rid of my global variables, or shouldn't I?
I hope you can show me or write for me a script example (or a link to it) of how I should do it. That's the fastest way I learn.
Put Variables Inside a Function Closure
One common way to eliminate a global is to put is inside a function closure:
(function() {
var declareYourFormerGlobalHere = 0;
// put all code that uses the variable inside this closure
// the variable persists for this code to use, but is not actually global
})();
Here's are some usage examples:
// example keeping track of a running count and a cached DOM element
(function() {
var cntr = 0, obj = document.getElementById("test");
setInterval(function() {
++cntr;
if (obj.value < cntr) {
// do something
} else {
// do something else
}
}, 1000);
})();
// example keeping track of a time of last click
(function() {
var timeOfLastClick = 0;
document.getElementById("run").addEventListener("click", function(e) {
var now = new Date().getTime();
// only process click if more than 2 seconds have passed since last click
if (now - timeOfLastClick > 2000) {
// OK to process the click
}
timeOfLastClick = now;
});
})();
Sometimes, you can actually enclose all your code or nearly all your code in a single closure like this and all your current globals become local variables inside the closure rather than actual globals. jQuery uses this technique to declare lots of persistent variables it uses, none of which are actual globally scoped.
Use a Single Namespace Object
Another common method of reducing the number of globals is to use the namespace concept. In this concept, you declare a single global object and put other persistent variables as properties of this single global object. This still leaves you with a single global variable, you can have as many properties as you want off this single global.
var myNamepaceObject = {};
myNamespaceObject.var1 = "foo";
myNamespaceObject.var2 = "whatever";
This technique is also used by jQuery as all globally accessible functions that jQuery offers are available off the jQuery object such as jQuery.extend() or jQuery.contains(). jQuery exposes a single global variable and many other globally accessible functions are then available as properties of that single global object.
Module Pattern
What is commonly known as the "module pattern" uses a combination of these above two techniques, where you have a single module variable that both uses properties and closure variables.
var MODULE = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
You can see a discussion of this design pattern in these references:
JavaScript Module Pattern: In-Depth
Learning Javascript - The Module Pattern
Mastering the Module Pattern
JavaScript module pattern with example
I'm convinced that I shouldn't, and I am more wondering HOW not to use them, and that I'm still unsure about.
load_chunks.js, load_images.js, render_map.js, player_actions.js, input.js, strongly hint to a procedural implementation, that is your architecture probably has several functional pieces and you pass data around between these functions. That's where your global variables are coming from.
So how do I get rid of my global variables (...)
To change that, you need to structure your system in an object or component based approach, that is:
encapsulate data + respective functions by objects in your problem domain, e.g. have a World object that contains Avatar, Buildings, Airborne objects etc. (or whatever your project is about).
separate the problem domain's logic from view logic (e.g. use a MVC architecture)
then your project organises the interactions between view and model objects by essentially exchanging messages between them.
To facilitate this, I suggest these fine frameworks, or some equivalents suitable for your run-time environment:
requirejs - to encapsulate modules into globally managed components
backbonejs - to have an efficient, proven model/view, class/object model (actually built for use with a REST-style backend, but that's not a strict requirement)
Code structure
Typically, I structure my applications such that there is one .js file per each object component/module. A module in this sense contains both the class definition and the corresponding collection. The modules are managed by requirejs and the class definitions are done using backbonejs.
I hope you can show me or write for me a script example
/* define a class e.g. in someclass.js */
define(['backbone'], function($B) {
var SomeClass = $B.Model.extend({
// all instance variables, methods etc. follow
someVar : value,
someMethod : function() { ... },
});
return SomeClass;
});
/* use the class, e.g. in app.js */
require(['someclass'], function(SomeClass) {
var instance = new SomeClass({ initial model attributes });
var value = instance.get('attribute');
instance.someMethod();
...
});
i had the same problem before but it was a big problem as we had a third party javascript code and our code live in clients websites so we should find a way to omit the appearance of global variable so to be short:
Use 1 global variable namespace and make all other to be properities for it:
GlobalVariable = {}
GlobalVariable.var1 = "var1"
GlobalVariable.var2 = "var2"
You can also make it more useful and divide it into groups:
GlobalVariable.helper = {}
GlobalVariable.helper.var1 = "var1"
GlobalVariable.helper.var2 = "var2"
so you can use same names under different groups.
and if you want to Omit it totally you can use:
(function(document, window) {
// all variables here is global only inside the scope
}(document, window));
One of the limitation of JS that bugs me the most is the poor ability to isolate code's execution.
I want to be able to control the context in which the code is executed, Something that achieve a similar effect to what Script.createContext & Script.runInContext in node.js does (node is using binding to the V8 engine, so i can't emulate their implementation).
Here is the some reason why I want to isolate code execution:
Isolate the code from the global namespace (the window object and the also the DOM) , but I however need to be able reference function call on objects exposed in the context which must be executed synchronous which makes it almost impossible using a WebWorker for isolation.
By isolate the execution of code it would possible also be able to deallocate its definitions when no longer needed (memory management).
I know one may achieve partly isolated execution by loading script into a iframe, this approach is however very heavy and uses a lot memory for a second instance of the DOM which isn't needed for what I'm trying to do.
I need to share constructor definition and also definitions of object which are shared between the isolated containers/contexts which both must run on the main UI thread. Mainly i want to use these isolated containers to host plugins/modules (mini-applications) which each presents and dynamically updates a viewport by calling drawing commands on their own Context2D object.
If these containers are not running on the main UI thread it wold be painfully hard to proxy calls such as ctx.measureText() and ctx.drawImage() would be all useless as image objects can't be created in a Worker.
Does someone know of future specification that would make this possible?
Are there any current (hidden) browser-side APIs that could be used to achieve this?
Would it be better utilize a virtual machine like Goggle's Dart VM and also re-implement my current codebase?
My current codebase is slightly above 20 000 lines of code.
Would it be better to re-implement the framework in *
The closest library I've seen for this is Caja.
Basically, in non-strict javascript code, there are many ways to get access to the global object (window in browsers), making true isolation a very hard problem. Caja does some iframing trickery to patch this, but to be honest I'm not exactly sure how it works.
You can isolate your code from the global namespace with a simple self executing function object:
(function() {
// all your code goes here
// nobody outside of your code can reach your top level variables here
// your top level variables are not on the window object
// this is a protected, but top level variable
var x = 3;
// if you want anything to be global, you can assign it to the window object.
window.myGlobal = {};
function myTopLevelFunction(x,y,z) {
// code here
}
})();
If you want to have multiple ones of these execution contexts and be able to share between them, then you will have to rendezvous via one publicly known location, either a truly global variable or a property on a known DOM object or something like that. It is relatively common to declare one global namespace object and use properties off that for any access to things you're sharing among modules. I know it isn't completely perfect, but it works. Here's an example of the rendevous using a single global namespace object:
// module AAA
(function() {
// module AAA code goes here
// set up global namespace object and whatever references we want to be global
window.myModuleTop = window.myModuleTop || {};
myModuleTop.AAA = {};
myModuleTop.AAA.myFuncA = function() {};
})();
// module BBB
(function() {
// module BBB code goes here
// set up global namespace object and whatever references we want to be global
window.myModuleTop = window.myModuleTop || {};
myModuleTop.BBB = {};
myModuleTop.BBB.myFuncB = function() {};
})();
Couldn't you use a closure like other answers mentioned and then use a shadow dom to ensure that the user can't get to the rest of the dom? Something like this:
var containerNode = someDomNode
var root = containerNode.createShadowRoot()
;(function(root){
var window = null, document = null, history = null,
screen = null, navigator = null, location = null
// isolated code goes here
})(root)
Caveats:
If you create other global objects outside the context of the isolated code, you need to explicitly shadow the variable like I did with window, document, etc, otherwise the isolated code will be to access it.
This won't work in browsers that don't have shadow dom obviously, unless your isolated code doesn't need to interact with the dom at all.
You have to be very careful that objects you do give the isolated code access to doesn't contain references to things you don't want it to have access to. Sometimes this is super error prone to do.
I'm making this suggestion because its plausible that it works, but I have no idea if there are additional ways to get to things like the window and document objects.
Is "standard" namespacing an option? Like:
var myNamespace = {};
myNamespace.myFunc = function() { return true; }
This approach is the simplest I can think of and may be the solution to many problems. Although not a real sandbox, it can let the code less error prone.
There is a proposal for Realms API, which seems to solve similar problems. It is still under discussion, but there is already a polyfill for it - realms-shim.
lets say that I have the following scenario:
var namespace = {};
(function($)
{
$.extend(namespace,
{
test1: function(someArray, someObj)
{
for(var i= 0, ii= someArray.length;i<ii;i++)
{
var text = someObj[someArray[i]];
// do something with text
}
},
test2: function(someArray, someObj,i,ii,text)
/*
see that the i,ii,text are unused parameters,
that will be used instead of variables
*/
{
for(i= 0, ii= someArray.length;i<ii;i++)
{
text = someObj[someArray[i]];
// do something with text
}
},
});
})(jQuery);
Now, the result of the test1 and test2 are the same... but what about the performance, memory usage...
Is there any difference between declaring the i,ii, test variables in the two ways presented above ?
I think that the test2, for example, is probably more efficient because the variables are in the local function scope so after the function exits, the execution context is destroy, releasing the resources used for the arguments... the variables will not be assigned to the global object 'window'.
So what method is performing best? and why?
[Edit]
Thanks all for your answers !
There is no problem if the code has readability issues... I`m only interested now about the performance/memory usage.
If you do not declare your variables with var i then they become implicitly global.
Always declare your variables. If you did any benchmarking on that you would find that declared local variables are actually faster then implied global variables. Also you don't leak to the global state that way.
Benchmark!.
As you can see the performance is identical.
In terms of memory usage, local variables (test1) are probably better as the compiler doesn't have to remember that the function has 5 parameters.
But that's a nano optimisation If you care about performance differences of this caliber write assembly instead. Go for readable and maintanable code.
[Edit]
Didn't notice "local" variables in method parameter. That is a readability killer! Don't do that. You will find that test1 is probably still more efficient.
Why don't you profile your code?
The variables are also local in test1. You are declaring them with var i.
There is no difference between these methods.
The variables in "test1" are all declared with var, so they're not global. Those two should be essentially the same.
test1 is faster, because every time JavaScript looks for symbols (such as a variable name) it starts by looking in the local scope. So by using global scope it has to look in more places to find the symbols. The same applies for parameters, but they are better than globals.
It may be miniscule, but declaring a new variable (text) in every iteration would require new memory allocation I believe. Though I'm not sure how javascript handles that. I usually declare variables beforehand and then assign values afterwards for that reason, but that is only because someone said "hey you should do it that way" and presented the same argument.
This question already has answers here:
How does this JavaScript/jQuery syntax work: (function( window, undefined ) { })(window)?
(5 answers)
Closed 8 years ago.
I guess using this pattern is the new hotness, but I don't understand what the advantage is and I don't understand the scoping implications.
The pattern:
(function(window, document, undefined){
window.MyObject = {
methodA: function() { ... },
methodB: function() { ... }
};
})(window, document)
So I have several questions about this.
Is there a particular advantage to encapsulating an object like this?
Why are window and document being fed in instead of just being accessed normally?
Why the heck is undefined being passed in?
Is attaching the object we're creating directly to window a particularly good idea?
I'm used to what I'll call the Crockford style of Javascript encapsulation (because I got it off the Douglas Crockford Javascript videos).
NameSpace.MyObject = function() {
// Private methods
// These methods are available in the closure
// but are not exposed outside the object we'll be returning.
var methodA = function() { ... };
// Public methods
// We return an object that uses our private functions,
// but only exposes the interface we want to be available.
return {
methodB: function() {
var a = methodA();
},
methodC: function() { ... }
}
// Note that we're executing the function here.
}();
Is one of these patterns functionally better than the other? Is the first one an evolution of the other?
Why are window and document being fed in instead of just being accessed normally?
Generally to fasten the identifier resolution process, having them as local variables can help (although IMO the performance improvements may be negligible).
Passing the global object is also a widely used technique on non-browser environments, where you don't have a window identifier at the global scope, e.g.:
(function (global) {
//..
})(this); // this on the global execution context is
// the global object itself
Why the heck is undefined being passed in?
This is made because the undefined global property in ECMAScript 3, is mutable, meaning that someone could change its value affecting your code, for example:
undefined = true; // mutable
(function (undefined) {
alert(typeof undefined); // "undefined", the local identifier
})(); // <-- no value passed, undefined by default
If you look carefully undefined is actually not being passed (there's no argument on the function call), that's one of the reliable ways to get the undefined value, without using the property window.undefined.
The name undefined in JavaScript doesn't mean anything special, is not a keyword like true, false, etc..., it's just an identifier.
Just for the record, in ECMAScript 5, this property was made non-writable...
Is attaching the object we're creating directly to window a particularly good idea?
It's a common way used to declare global properties when you are on another function scope.
This particular style does bring some benefits over the "Crockford" style. Primarily, passing window and document allows the script to be more efficiently minified. A minifier can rename those parameters to single-character names, saving 5 and 7 bytes respectively per reference. This can add up: jQuery references window 33 times and document 91 times. Minifying each token down to one character saves 802 bytes.
Additionally, you do get an execution speed benefit. When I first read #joekarl's assertion that it provides a performance benefit, I thought, "that seems rather spurious." So I profiled the actual performance with a test page. Referencing window one hundred million times, the local variable reference provides a modest 20% speed increase (4200 ms to 3400ms) in Firefox 3.6 and a shocking 31,000% increase (13 sec to 400ms) in Chrome 9.
Of course, you're never going to reference window 100,000,000 times in practice, and even 10,000 direct references only take 1ms in Chrome, so the actual performance gain here is almost completely negligible.
Why the heck is undefined being passed in?
Because (as mentioned by #CMS) the token undefined is actually undefined. Unlike null, it has no special meaning, and you're free to assign to this identifier like any other variable name. (Note, however, that this is no longer true in ECMAScript 5.)
Is attaching the object we're creating directly to window a particularly good idea?
The window object is the global scope, so that's exactly what you're doing at some point, whether or not you explictly write "window." window.Namespace = {}; and Namespace = {}; are equivalent.
I'm with you in using Crockford's style.
To answer your questions
1.Is there a particular advantage to encapsulating an object like this?
The only advantage I can see is by making window and document local variables instead of global variables, you get some added safety by not being able to directly overwrite either one and also some performance gain by them both being local.
2.Why are window and document being fed in instead of just being accessed normally?
Addressed above. Local variables tend to be faster, but with jit compiling these days thats becoming nominal.
3.Why the heck is undefined being passed in?
No clue....
4.Is attaching the object we're creating directly to window a particularly good idea?
Probably not, but I would still stick with Crockford's pattern as attaching the function to the window object exposes it to the rest of the global stack through the window object as opposed to exposing it through a non-standard namespace.
I think this is mostly for code that needs to run in multiple window contexts. Say you have a complex application with lots of iframes and/or child windows. They all need to run the code in MyObject, but you only want to load it once. So you load it in whatever window/frame you choose, but you create a MyObject for each window/frame with references to the proper window and document.
Taking an undefined argument is trying to protect against the fact that undefined can be changed:
undefined = 3;
alert(undefined);
See CMS's answer about how this improves safety.
My intuition is that it's a good idea to encapsulate blocks of code in anonymous functions like this:
(function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
})();
Because I'm not going to need aVar again, so I assume that the garbage collector will then delete aVar when it goes out of scope. Is this right? Or are interpreters smart enough to see that I don't use the variable again and clean it up immediately? Are there any reasons such as style or readability that I should not use anonymous functions this way?
Also, if I name the function, like this:
var operations = function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
};
operations();
does operations then necessarily stick around until it goes out of scope? Or can the interpreter immediately tell when it's no longer needed?
A Better Example
I'd also like to clarify that I'm not necessarily talking about global scope. Consider a block that looks like
(function() {
var date = new Date(); // I want to keep this around indefinitely
// And even thought date is private, it will be accessible via this HTML node
// to other scripts.
document.getElementById('someNode').date = date;
// This function is private
function someFunction() {
var someFuncMember;
}
// I can still call this because I named it. someFunction remains available.
// It has a someFuncMember that is instantiated whenever someFunction is
// called, but then goes out of scope and is deleted.
someFunction();
// This function is anonymous, and its members should go out of scope and be
// deleted
(function() {
var member;
})(); // member is immediately deleted
// ...and the function is also deleted, right? Because I never assigned it to a
// variable. So for performance, this is preferrable to the someFunction
// example as long as I don't need to call the code again.
})();
Are my assumptions and conclusions in there correct? Whenever I'm not going to reuse a block, I should not only encapsulate it in a function, but encapsulate it in an anonymous function so that the function has no references and is deleted after it's called, right?
You're right that sticking variables inside an anonymous function is a good practice to avoid cluttering up the global object.
To answer your latter two questions: It's completely impossible for the interpreter to know that an object won't be used again as long as there's a globally visible reference to it. For all the interpreter knows, you could eval some code that depends on window['aVar'] or window['operation'] at any moment.
Essentially, remember two things:
As long as an object is around, none of its slots will be magically freed without your say-so.
Variables declared in the global context are slots of the global object (window in client-side Javascript).
Combined, these mean that objects in global variables last for the lifetime of your script (unless the variable is reassigned). This is why we declare anonymous functions — the variables get a new context object that disappears as soon as the function finishes execution. In addition to the efficiency wins, it also reduces the chance of name collisions.
Your second example (with the inner anonymous function) might be a little overzealous, though. I wouldn't worry about "helping the garbage collector" there — GC probably isn't going to run in the middle that function anyway. Worry about things that will be kept around persistently, not just slightly longer than they otherwise would be. These self-executing anonymous functions are basically modules of code that naturally belong together, so a good guide is to think about whether that describes what you're doing.
There are reasons to use anonymous functions inside anonymous functions, though. For example, in this case:
(function () {
var bfa = new Array(24 * 1024*1024);
var calculation = calculationFor(bfa);
$('.resultShowButton').click( function () {
var text = "Result is " + eval(calculation);
alert(text);
} );
})();
This results in that gigantic array being captured by the click callback so that it never goes away. You could avoid this by quarantining the array inside its own function.
Anything that you add to the global scope will stay there until the page is unloaded (unless you specifically remove it).
It's generally a good idea to put variables and function that belong together either in a local scope or in an object, so that they add as little as possible to the global namespace. That way it's a lot easier to reuse code, as you can combine different scripts in a page with minimal risks for naming collisions.