I want to know the overhead of JavaScript closures. Suppose I have the following function:
function sum(arr, sumMethod) {
var totalSize = 0;
for (index = 0; index < arr.length; ++index) {
totalSize += sumMethod(arr[index]);
}
return totalSize;
}
If I want to know the total size of all my transfers, then I could use a global accessor function to obtain the size of a transfer. This function is passed to sum:
// Use a "global" method that is initialize only once
function getTransferSize(transfer) { return transfer.size };
...
// Obtain the total size of all transfers (called pretty often)
var totalTransferSize = sum(transfers, getTransferSize);
Another approach is to inline the accessor like this:
// Obtain the total size of all transfers (called pretty often)
var totalTransferSize = sum(transfers, function (transfer) { return transfer.size });
I would think the closure is only "compiled" once and reused over and over again, so the actual execution performance would be equal. A collegue of mine thinks that the closure is created over and over again and it hurts performance.
Can anyone explain what is the preferred method?
REMARK: I am actually using CoffeeScript, which makes closures much more readable. In CoffeeScript the code would look like this:
totalTransferSize = sum transfers, (t) -> t.size
I find this much more readable then using a global accessor function, so I would prefer to inline the accessor.
A collegue of mine thinks that the closure is created over and over again
Yes. Every time the function expression is evaluated, a new function object is instantiated.
and it hurts performance.
Unlikely. If you'd really care, measure it. The instantiation is probably much cheaper than the loop with the calls.
I would think the closure is only "compiled" once and reused over and over again
Yes, the code is compiled only once and shared by all the function instances.
so the actual execution performance would be equal.
Of the single call, yes.
Related
The function I want to create requires an access myObject.
Is it better to create the helper function inside the main function so I have access to myObject with the scope.
Or should I make the helper function outside of myFunction and pass myObject as a parameter?
EDIT: Could I get memory-leak problem with those methods?
//Method 1
var myFunction = function(myObject){
var helper = function(i){
return console.log(i,myObject[i]);
}
for(var i in myObject){
var callback = helper(i);
}
}
//Method 2
var myFunction = function(myObject){
for(var i in myObject){
var callback = helper(i,myObject);
}
}
var helper = function(i,myObject){
return console.log(i,myObject[i]);
}
I assume you're asking for performance.
Here is a jsperf to test it for you (Yup, this exists and is very neat).
So in running the tests a bunch of times I note that neither method clearly wins. It's very close and almost certainly doesn't matter. I also note that on Windows 8.1, IE 11 blows Chrome out of the water, it's not even close - like by a factor of 20. That's a neat little result but not really indicative of real world code performance and likely we're just hitting an optimized case. Within IE the in-function version is a tiny-almost-irrelevant bit faster.
You can play with the inputs somewhat (for example I just passed in a small object, maybe a big one has different results), but I'm ready to call a preliminary conclusion: Don't worry about performance here. Use whichever one makes more sense for your specific case in terms of code clarity.
Apart from performance benefit mentioned by George Mauer, I think it will be a good idea to keep it inside to keep global context clean.
Different functions can have their own helpers defined inside them with same name rather than having function1Helper, function2Helper... in the global context.
for(var i = 0; i < 100; i++){
var foo = 5;
}
It works ...but is this bad?
I know I can declare var foo outside, but why do that when I'm only going to use it in the loop?
Over time my personal style has grown into a preference for declaring variables where they "actually are" in the "mind" of the particular language I am working in. For JavaScript this means putting variable and function declarations in the positions where the language would hoist them anyway.
This is for clarity, precise communication, understanding, maintainability, to keep my own mental processes parallel with the processes of the language, just to mention a few good reasons.
So in this particular case, I would not put a var foo = 5; declaration into the body of a for loop, for the simple reason that it is not doing what it looks like it is doing, i.e., it is not in fact redeclaring/re-scoping the variable with every iteration. (Placing the var declaration in the initialization portion of the for loop's header (initialization; condition; afterthought) would be more reasonable, and certainly the correct place to put it in languages that do have block-level variables, such as when JavaScript finishes adopting the let-style declaration for block-level scope.)
Notes:
This practice may not seem "normal." My mind prefers to keep variables "close" to their use, and my current practice does not come naturally to the way my mind works. But as a programmer through the years, experiences with confusion, bad communication, misunderstanding, unmaintainable code impossible to unravel, etc., have more than justified the extra discipline that it takes me to follow this style of declaring variables in the locations corresponding to their actual scope, regardless of the language.
One extra benefit of this practice for me has been that it encourages me to keep my functions modular and reasonable in size.
Along the same lines, following this practice automatically helps keep my code organized in a sensible way. For instance, if putting my functions first causes there to be excessive functions before the code I am actually working on, and I therefore get irritated about having to go down two pages to edit my program, following this style automatically gives me incentive to organize my code into an appropriate structure of distinct files.
P.S. One could bring up a point that some functions are so long that this practice makes variable declarations end up pages away from where they are used. Yes, I have seen code where that is true, and perhaps even code where that cannot be helped. Yet I can't help observing the parallel that is equally true for authors of prose as it is for computer programmers. As skill level grows, the lengths of authors' sentences (and sizes of programmers' functions) tend to grow, and then as the skill level continues to grow yet higher, the lengths of sentences (and sizes of programmer's functions) tend to shorten once more.
It is bad because it gives the false impression that i and foo are local variables.
for(var i = 0; i < 100; i++){
var foo = 5;
}
foo; // 5
This might not be a problem with simple code, but if you use closures it becomes apparent that there is only one foo:
var counters = [];
for (var i = 0; i < 100; i++) {
var foo = 5;
counters.push(function() { foo++; return foo; });
}
counters[0](); // 6
counters[0](); // 7
counters[1](); // 8 (!)
To create foo in a different scope a function needs to be introduced:
var counters = [];
for (var i = 0; i < 100; i++) {
(function() {
var foo = 5;
counters.push(function() { foo++; return foo; });
})();
}
counters[0](); // 6
counters[0](); // 7
counters[1](); // 6
Here is a real-life example of things going wrong due to this: setTimeout in for-loop does not print consecutive values
Since JavaScript 1.7 you can use the let keyword (see MDN) to create true local variables.
Example :
var myFunctArray=new Array();
for(var i=0; i<10; i++) {
addValues(i);
}
function addValues(myPoint)
{
myFunct=function () {
var myVar="Line " + myPoint;
console.log(myVar);
}
myFunctArray.push(myFunct);
}
myFunctArray[3]();
when I call the 4° function, how can it remembers the value of myPoint? In fact it is Line 3 the output, so myPoint value must be "stored" somewhere, for each function.
So, it stores 10 "definitions" of myFunct in the stack memory?
Hope it is clear what I mean.
It's called a closure. Any variables that are currently in scope when you create a new function are associated with that closure.
So, it stores 10 "definitions" of myFunct in the stack memory?
Yes, it does.
Your array contains ten closures, each of which has captured its own version of myPoint.
Thiefmaster answered your question pretty much. Yes, this code will use more and more memory, depending on how many closures your array contains. It has to be said that most modern engines will assign a reference to the function assigned to the MyFunct variable and a specific "call object" that contains the closure vars. In other words, your array will look something along the lines of:
myFuncArray[0] = {call:
{myPoint:'Whatever value was passed to the addValues function the first time'},
valueOf: myFunct};
//the actual value is a reference to myFunct
//JS provides an implicit link to the call property, which is bound to this particular reference
myFuncArray[1] = {call:
{myPoint:'The value passed to addValues the second time'},
valueOf: myFunct};
You don't have access to the object as such, but this is just the way to think of how JS will keep things organized in memory.
Slightly off topic, but you're creating an implied global with your MyFunct variable:
function addValues(myPoint)
{
var anotherClosureVar = 'This will be accessible, too: it\'s part of the closure';
var myFunct = function()
{//use var to declare in addValues scope, instead of using an implied global
var myVar="Line " + myPoint;
console.log(myVar);
console.log(anotherClosureVar);//will work, too
};
myFunctArray.push(myFunct);
}
All in all, if this is your code, memory shouldn't be that big of an issue. Even if this code were to run on an old JScript engine, it'll take some time before you've used up a meaningful amount of memory. Still, it's a good habit to think about stuff like this, and I do hope I made sense here, I'm not a native speaker, which makes explaining the more abstract aspects of JS somewhat tricky
I have a variable that is being set based on if it an object has a length as one of its properties. If not then I need to check if one of the properties exists. If so then get the first array stored in that object and return the length, else the variable is set to one. This could be combined all in statement like this.
var b=someObject;
var len = b.num||(b.arrs?(function(a){for(var x in a)return a[x].length})(b.arrs):false)||1;
The other way of doing this is pulling out the function and doing it like this
function getLength(a){for(var x in a)return a[x].length})
var b=someObject;
var len = b.num||(b.arrs?getLength(b.arrs):false)||1;
I was wondering if there is a performance penalty for doing it one way compared to the other? Is there a difference in how the javascript engine looks at them? The reason I would prefer the first way is it keeps me from having a bunch of extra helper functions.
The anonymous inline version is executed and discarded. Whereas the separate function instance is
a) Kept in memory and popped out with the rest of the local variables, if it is declared within a function
b) Kept in memory for the life time of the page if it is defined in global space as a member of the window object.
So if you are unlikely to need it again, it is best to go the anonymous inline route i believe.
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.