not looping through all items in array - javascript

this.draw = function() {
console.log(this.buttonList.length);
for(a = 0; a < this.buttonList.length; a++) {
console.log(this.buttonList.length, a);
this.buttonList[a].draw();
}
};
So I have this function within an object, and it's not working the way I expected it to. When I run it with the above console.log statements, it logs this on the console:
2
2 0
This seems to tell me that my for loop is not looping through every item on the array, and I've been scratching my head over why that would be for a quite a while now. Does anyone know why it's only performing the action for a = 0?
edit: I don't know if this makes a difference, but this function is called about 60 times every second.

Adding var would probably fix it :
this.draw = function() {
console.log(this.buttonList.length);
for(var a = 0; a < this.buttonList.length; a++) {
console.log(this.buttonList.length, a);
this.buttonList[a].draw();
}
};
There's very probably another point of your code where you change a. You should be careful with the variable declarations.

There are atleast three possibilities for the behavior:
a is overwritten (as per dystroys answer).
All elements in buttonList don't have a draw function.
this in the function definition of draw is an element in the buttonList.
The first two possibilities are easy to fix but the third one depends on what your intentions are, i.e. what do you wish to accomplish. To fix it we need more information.
Any one of the three possibilities (or combinations of the possibilities) could account for the behavior.
The first possibility is explained by dystroy.
The second possibility will stop excecution if an element doesn't have a draw function. In this case it seems to be the first element.
The third possibility will render in a stack overflow due to infinite recursion. The draw function is called over and over again just logging to console 2 then 2 0 until all the stack is consumed at which point the execution stops.

Related

Why cant I scroll browser window in a loop in console?

I want to scroll down the browser window in a loop in console. I want it so that every time a scroll down (x)px down I stop, do something and then scroll (x)px again and then stop etc. until the page with ends (its a very long one, I want to parse info from it).
But when I started I stumbled upon an issue, that the scrolling function is executed only once, after the loop ends.
let i = 0;
scrollDownTillEnd = () => {
for(i; i<100; i++) {
window.scrollBy(0, 1000);
};
scrollDownTillEnd();
(it is a simplified example, but the idea should be clear)
I put the code in the console, being on a page I want to scroll, and get then the value of i at the end of the loop and only one scroll down.
Please, explain me, why this piece of code behaves like this and how to make it work, as I mentioned before (in every loop it scrolls a little bit).
Thank you!
Let me help address a few issues going on here.
1) You have an infinite loop going on because you are not checking that i is less than 100 even though you are incrementing it each time. You need to check that i < 100 so that the loop will eventually end. In your loop, 0 will always be less than 100 so the loop will never end.
2) You have a syntax error in your example because you're not actually closing out the scrollDownTillEnd function with a curly brace before calling the function itself.
3) Lastly, as good practice, you need to reset your i variable to 0 each time so that we can run this piece of code over and over again. The way you have it set up in your example, since i will be equal to 100 at the end of the first run, the loop won't ever run again after that until you reset i to 0 again. The easiest way to do this is to just initialize i to a value of 0 each time you execute this loop.
Try something like this:
scrollDownTillEnd = () => {
for(let i = 0; i < 100; i++) {
window.scrollBy(0, 1000);
};
};
scrollDownTillEnd();
You can use setInterval() since for loop will executes only once
function scrollDownTillEnd(countryDropdownList)
{
let scrollingInterval = setInterval(function(){
window.scrollBy(0,1000)
// write your condition
if (window.scrollHeight > 10000)
{
clearInterval(scrollingInterval)
}
},100)
}
scrollDownTillEnd();

Perfomance: Switch vs Polymorphism

I usually prefer polymorphism instead of switch when it possible. I find it more readable and it requires fewer lines. I believe these facts are enough to continue to use it. But what about performance? I've create a pretty simple (and bad) bench and it looks that switch is faster in my case. Could you please explain why?
https://jsfiddle.net/oqzpfqcg/1/
var class1 = { GetImportantValue: () => 1 };
var class2 = { GetImportantValue: () => 2 };
var class3 = { GetImportantValue: () => 3 };
var class4 = { GetImportantValue: () => 4 };
var class5 = { GetImportantValue: () => 5 };
getImportantValueSwitch = (myClassEnum) => {
switch (myClassEnum.type) {
case 'MyClass1': return 1;
case 'MyClass2': return 2;
case 'MyClass3': return 3;
case 'MyClass4': return 4;
case 'MyClass5': return 5;
}
}
getImportantValuePolymorphism = (myClass) => myClass.GetImportantValue();
test = () => {
var INTERATION_COUNT = 10000000;
var t0 = performance.now();
for (var i = 0; i < INTERATION_COUNT; i++) {
getImportantValuePolymorphism(class1);
getImportantValuePolymorphism(class2);
getImportantValuePolymorphism(class3);
getImportantValuePolymorphism(class4);
getImportantValuePolymorphism(class5);
}
var t1 = performance.now();
var t2 = performance.now();
for (var i = 0; i < INTERATION_COUNT; i++) {
getImportantValueSwitch({type: 'MyClass1'});
getImportantValueSwitch({type: 'MyClass2'});
getImportantValueSwitch({type: 'MyClass3'});
getImportantValueSwitch({type: 'MyClass4'});
getImportantValueSwitch({type: 'MyClass5'});
}
var t3 = performance.now();
var first = t1 - t0;
var second = t3 - t2;
console.log("The first sample took " + first + " ms");
console.log("The second sample took " + second + " ms");
console.log("first / second = " + (first/second));
};
test();
So as far as I understand the first sample has one dynamic/virtual runtime call myClass.GetImportantValue() and that's it. But the second has one dynamic/virtual runtime call as well myClassEnum.type and then check the condition in the switch.
Most probably I have some mistakes in the code but I cannot find it. The only thing that I suppose can affect result is performance.now(). But I think it does not affect so much.
V8 developer here. Your intuition is right: this microbenchmark isn't very useful.
One issue is that all your "classes" have the same shape, so the "polymorphic" case is in fact monomorphic. (If you fix this, be aware that V8 has vastly different performance characteristics for <= 4 and >= 5 polymorphic cases!)
One issue is that you're relying on on-stack replacement (OSR) for optimization, so the performance impact of that pollutes your timings in a misleading way -- especially for functions that have this pattern of two subsequent long-running loops: they get OSR-optimized for the first loop, deoptimized in the middle, then OSR-optimized again for the second loop.
One issue is that the compiler inlines many things, so the actually executed machine code can have a very different structure from the JavaScript code you wrote. In particular in this case, getImportantValueSwitch gets inlined, the {type: 'MyClass*'} constant object creations get elided, and the resulting code is just a few comparisons, which are very fast.
One issue is that with small functions, call overhead pretty much dominates everything else. V8's optimizing compiler doesn't currently do polymorphic inlining (because that's not always a win), so significant time is spent calling the () => 1 etc functions. That's unrelated to the fact that they're dynamically dispatched -- retrieving the right function from the object is pretty fast, calling it is what has the overhead. For larger functions, you wouldn't notice it much, but for almost-empty functions, it's quite significant compared to the switch-based alternative that doesn't do any calls.
Long story short: in microbenchmarks, one tends to measure weird effects unrelated to what one intended to measure; and in larger apps, most implementation details like this one don't have measurable impact. Write the code that makes sense to you (is readable, maintainable, etc), let the JavaScript engine worry about the rest! (Exception: Sometimes profiling indicates that your app has a particular bottleneck -- in such cases, hand-optimizing things can have big impact, but that's usually achieved by taking context into account and making the overall algorithm / control flow more efficient, rather than following simple rules of thumb like "prefer polymorphism over switch statements" (or the other way round).)
I do not see a "mistake" in your script. Although I really do not encourage performance testing this way, I might still be able to say a couple of things based on my intuition. I do not have solid, well tested results with control groups etc so take everything I say with a pinch of salt.
Now, for me it is quite normal to assume that the first option is gonna eat the dust of the second because there are couple of things more expensive than variable access in js:
object property access (presumably O(1) hash table, but still slower than variable access)
function call
If we count the function call and object access:
first case: 5 call [to getImportantValuePolymorphism] x (1 object access [to myClass] + 1 function call [to GetImportantValue] ===> TOTAL OF 10 function calls + 5 object access
second case: 5 call [to getImportantValueSwitch ] + 5 object access [to MyClassEnum] ===> TOTAL 5 function calls + 5 object access
One more things to mention, that in the first case, you have a function that calls another function so you end up with a scope chain. Net effect of this is minute, but still detrimental in means of performance.
If we account all the above factors, first will be slower. But how much? That is not easy to answer as it will depend on vendor implementations but in your case it about 25 times slower in chrome. Assuming we have double the function calls in the first case and a scope chain, one would expect it to be 2 or 3 times slower, but not 25.
This exponential decrease in performance I presume is due to the fact that you are starving the event loop, meaning that when you give a synchronous task to js, since it is single threaded, if the task is a cumbersome one, the event loop cannot proceed and gets stuck for good second or so. This question comes around when people see strange behavior of setTimeout or other async calls when they fire way off from the target time frame. This is as I said, due to the fact that previous synchronous task is taking way too long. In your case you have a synchronous for loop that iterates 10 million times.
To test my hypothesis, decrease the ITERATION_COUNT to 100000, that is 100 times less, you will see that in chrome, the ratio will decrase from ~20 to ~2. So the bottom line 1: Part of the inefficiency you observe is stemming from the fact that you are starving the event loop, but it still does not change the fact that first option is slower.
To test that function calls are indeed the bottle neck here, change the relevant parts of your script to this:
class1 = class1.GetImportantValue;
class2 = class2.GetImportantValue;
class3 = class3.GetImportantValue;
class4 = class4.GetImportantValue;
class5 = class5.GetImportantValue;
and for the test:
for (var i = 0; i < INTERATION_COUNT; i++) {
class1();
class2();
class3();
class4();
class5();
}
Resulting fiddle: https://jsfiddle.net/ibowankenobi/oqzpfqcg/2/
This time you will see that the first one is faster because it is (5 function calls) vs ( 5 function calls + 5 object access).

Javascript Timeout between for loop?

So it's probably some mis-understanding on the best way to use the setTimeout method provided by javascript but im having trouble implementing it in a way that makes sense.
Essentially I have an Array with numbers between 1-4 and each number corresponds to a button getting let up.
for(let i = 0;i < arr.length;i++){
view.renderPane(arr[i]) //All this does is set the .css
view.renderPane is pretty simple:(I have a separate function that clears(sets opacity back to .5) it, but if possible i'd like to just put that in here.
renderPane(pane){
$("."+pane).css("opacity", "1");
console.log("Activating Pane "+ pane)
}
So I tried setting up a timeout thinking I could call the renderPane within the timeout, but all it did was set up a bunch of timeouts that basically fired off after X seconds (or milliseconds). Is there a way I can call the renderPane(pane) function every 1 second (to set up a delay) inside this for loop? or will I need to set up something else?
No need to use a loop, just create a function which continuously schedules itself with setTimeout until it's done — in this case, it removes an item from the array in each call and stops when the array is empty:
(function callee() {
view.renderPane(arr.shift());
if (arr.length)
setTimeout(callee, 1000);
})();
Example: https://jsfiddle.net/2fwht35d/
There are many other ways to implement this behaviour, but this should give you a good starting point.

Improve performance in js `for` loop

So I'm looking for some advice on the best method for toggling the class (set of three) of an element in a loop ending at 360 iterations. I'm trying to avoid nested loops, and ensure good performance.
What I have:
// jQuery flavour js
// vars
var framesCount = '360'; // total frames
var framesInterval = '5000'; // interval
var statesCount = 3; // number of states
var statesCountSplit = framesInterval/statesCount;
var $scene = $('#scene');
var $counter = $scene.find('.counter');
// An early brain dump
for (f = 1; f < framesCount; f += 1) {
$counter.text(f);
for (i = 1; i < statesCount; i += 1) {
setTimeout(function() {
$scene.removeClass().addClass('state-'+i);
}, statesCountSplit);
}
}
So you see for each of 360 frames there are three class switchouts at intervals. Although I haven't tested I'm concerned for the performance hit here once that frames value goes into the thousands (which it might).
This snippet is obviously flawed (very), please let me know what I can do to make this a) work, b) work efficiently. Thanks :-)
Some general advice:
1) Don't declare functions in a loop
Does this really need to be done in a setTimeout?
for (i = 1; i < statesCount; i += 1) {
setTimeout(function() {
$scene.removeClass().addClass('state-'+i);
}, statesCountSplit);
}
2) DOM operations are expensive
Is this really necessary? This will toggle so fast that you won't notice the counter going up. I don't understand the intent here, but it seems unnecessary.
$counter.text(f);
3) Don't optimize early
In your question, you stated that you haven't profiled the code in question. Currently, there's only about 1000 iterations, which shouldn't be that bad. DOM operations aren't too bad, as long as you aren't inserting/removing elements, and you're just modifying them.
I really wouldn't worry about performance at this point. There are other micro-optimizations you could apply (like changing the for loop into a decrementing while loop to save on a compare), but you gave no indication that the performance is a problem.
Closing thoughts
If I understand the logic correctly, you're code doesn't match it. The code will currently increment .counter as fast as the processor can iterate over your loops (should only take a few milliseconds or so for everything) and each of your "class switchouts" will fire 360 times within a few milliseconds of each other.
Fix your logic errors first, then worry about optimization if it becomes a problem.
Don't use a for loop for this. This will generate lots of setTimeout events which is known to slow browsers down. Use a single setTimeout instead:
function animate(framesCount, statesCount) {
$scene.removeClass().addClass('state-'+statesCount);
if (framesCount) {
setTimeout(
function(){
animate(framesCount-1,(statesCount%3)+1);
},
statesCountSplit
);
}
}
animate(360*3,1);

jquery/js too slow while operating over 2000 rows

I have 2000 rows of data as follows
<div class="rr cf">
<span>VLKN DR EXP</span>
<span>01046</span>
<span>VELANKANNI</span>
<span>20:30</span>
<span>DADAR</span>
<span>10:00</span>
</div>
On a button click I am checking for text within them and updating the display of each row to block or none. The code that does this is
$('.rr').each(function(){
this.style.display="block";
});
var nodes = $(".rr");
for(var i=0;i < nodes.length; i++) {
// if data found
nodes.get(i).style.display="block";
// else
nodes.get(i).style.display="none";
}
This seems to be possibly very slow. I get chrome alert box as to kill the page.
Any ideas? what optimization can I do here?
Local Variables and Loops
Another simple way to improve the performance of a loop is to
decrement the iterator toward 0 rather than incrementing toward the
total length. Making this simple change can result in savings of up to
50% off the original execution time, depending on the complexity of
each iteration.
Taken from: http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html
Try saving the nodes.length as a local variable so that the loop doesn't have to compute it each time.
Also, you can store nodes.get(i) into a local variable to save some time if you are accessing that data a lot.
If the order isn't important, consider decrementing your for loop towards 0.
jQuery's each() loop is a bit slower than looping through the set yourself as well. You can see here that there is a clear difference.
Very simple example
You'll see that in my example, I've condensed the loop into a while loop:
var nodes = $(".rr span");
var i = nodes.length;
while(i--){
if(i%2 === 0){
nodes.get(i).style.color = "blue";}
}​
Notice that the while loop decrements i through each iteration. This way when i = 0, the loop will exit, because while(0) evaluates to false.
"Chunking" the Array
The chunk() function is designed to process an array in small chunks
(hence the name), and accepts three arguments: a “to do” list of
items, the function to process each item, and an optional context
variable for setting the value of this within the process() function.
A timer is used to delay the processing of each item (100ms in this
case, but feel free to alter for your specific use). Each time
through, the first item in the array is removed and passed to the
process() function. If there’s still items left to process, another
timer is used to repeat the process.
Have a look at Nick Zakas's chunk method defined here, if you need to run the loop in sections to reduce the chance of crashing the browser:
function chunk(array, process, context){
setTimeout(function(){
var item = array.shift();
process.call(context, item);
if (array.length > 0){
setTimeout(arguments.callee, 100);
}
}, 100);
}
Using createDocumentFragment()
Since the document fragment is in memory and not part of the main DOM
tree, appending children to it does not cause page reflow (computation
of element's position and geometry). Consequently, using document
fragments often results in better performance.
DocumentFragment are supported in all browsers, even Internet Explorer
6, so there is no reason to not use them.
Reflow is the process by which the geometry of the layout engine's
formatting objects are computed.
Since you are changing the display property of these elements iteratively, the page mush 'repaint' the window for each change. If you use createDocumentFragment and make all the changes there, then push those to the DOM, you drastically reduce the amount of repainting necessary.
Firstly, where are the delays occurring - in the jquery code, or the data check? If it is the jquery, you could try detaching the data container element (ie the html element that contains all the .rr divs) from the DOM, make your changes, and then re-attach it. This will stop the browser re-processing the DOM after each change.
I would try
1) set display of the common parent element of all those divs, to "none"
2) loop through divs, setting display as appropriate
3) set parent element display back to block
I believe this will help because it gives the browser the opportunity to aggregate the rendering updates, instead of forcing it to fully complete each single time you change the display property. The visibility of all the child node are irrelevant if the parent isnt displayed, so the browser no longer has a need to render a change in each child until the parent becomes visible again.
ALso, I fail to see the purpose of you first looping through them all and setting them all to block before you loop again and set them to their intended value.
Don't use jQuery here, jQuery will just slow things down here.
var elements = document.getElementsByClassName('rr'),
len = elements.length;
for(var i = 0; i < len; i++)
{
var ele = elements[i];
if(ele.innerHTML.search(/01046/) != -1)
ele.style.display = "none";
}
This should be much faster.
I'm also having performance problems while looping through roughly 1500 items.
As you might have guessed, the loop itself isn't the bottleneck. It's the operation you do within it that's the problem.
So, what I migrated the load using setTimeout. Not the prettiest of solutions but it makes the browser responsive between the updates.
var _timeout_ = 0;
for(var i=0;i < nodes.length; i++)
{
setTimeout(
(function(i)
{
return function()
{
if(stuff)
{
nodes.get(i).style.display="block";
}
else
{
nodes.get(i).style.display="none";
}
}
})(i),
_timeout_
);
_timeout_ += 4;
}
This will delay every update with 4 milliseconds, if the operation takes longer, the browser will become unresponsive. If the operation takes only 2 milisecond on your slowest browser, you can set it to 3, etc. just play around with it.

Categories