Most efficient JavaScript countdown timer implementation I have this timer working already(jsbin):

HTML:

  &lt;input id="m" type="number" value="0" min="0" max="59"/&gt;
  &lt;input id="s" type="number" value="2" min="0" max="59"/&gt;
  &lt;input id="start" type="button" value="Start!" /&gt;
  &lt;output&gt;00:00&lt;/output&gt;


JavaScript:

var o = document.querySelector('output'),
m = document.querySelector('#m')
s = document.querySelector('#s'),
start = document.querySelector('#start');


start.addEventListener('click', function(){
    var mm = parseInt(m.value),
        ss = parseInt(s.value);
    timer = function(){
        if(mm&gt;0){
            if(ss&gt;0){
                ss--;
            }
            else{
                mm--;
                ss = 59;
            }
            setTimeout("timer()", 1000);
            o.value = (mm&lt;10 ? '0' + mm : mm) + ":" + (ss&lt;10 ? '0' + ss : ss);
        }
        else{
            if(ss&gt;0){
                ss--;
                o.value = "00:" + (ss&lt;10 ? '0' + ss : ss);
                setTimeout("timer()", 1000);
            }
        }
    }

    timer();
}, false);


It seems a lot of code for just a timer. Is it possible to implement this with less code? Maybe with loops, Date object or something else?

This code have problem and that is number of items in call stack when the time is big enough. I tried to write same code with while or for but I couldn't get a good result.

MY QUESTION is how to write this countdown with for or while?
document.querySelector("#id") is just a costly version of document.getElementById("id"). document.getElementById is the fastest way to select an element in your page (to the smartasses of you: besides document.head, document.body etc)

document.querySelector("tagname") is also just a costly version of document.getElementsByTagName("tagname")[0]. Coincidentally, that's the second fastest way to get an element.

document.querySelector and its array-like version are only useful for compound statements that are either too long or too difficult to do with "regular" DOM methods. One might argue that if your html is compound and complex, you're doing it wrong, and they'd most likely be right.

If I were you, I'd also do future-you a favor and name your variables in a way that makes sense.

So, what do we have so far?

var output = document.getElementsByTagName("output")[0],
    minutes = document.getElementById("m"),
    seconds = document.getElementsById("m"),
    start = document.getElementById("start");


Moving on. The event listener is fine, now about parsing integers...

Try this piece of code: parseInt("08"). The result is 0. Why, you ask? Well, if you don't pass a radix as a second parameter, parseInt will be nice enough to guess what you mean. parseInt sees that your string begins in a 0 and, of course, assumes the number is in octal! Why wouldn't it be?

Point: either pass a radix like this: parseInt(string, 10) or use parseFloat, which will always assume a decimal number. Whichever you like best, though I once heard that parseFloat is faster, dunno if that's true. I personally prefer parseFloat, for no obvious reason

So we get:

var mm = parseFloat(minutes.value),
    ss = parseFloat(seconds.value);


Magnificent.

This line:

timer = 


Contains one of the most widely made errors in javascript. It's called implied global.

Basically, when you omit the var statement, the variable definition list gets appended to the global object (which window refers to). So:

function foo() { answer = 42; }
foo();
window.answer === 42;


Never omit the var statement. Even if you do wish to append a variable to the global object, do it explicitly (window.answer = 42;). Better that then let someone scratch their head trying to figure out how magic variables appeared from seemingly nowhere.

Besides one more thing, your code is fine. What's that other thing, you ask? setTimeout

When you pass a string to setTimeout, it's the same as calling eval. It evaluates the string. That's slow and bad. Instead, pass a function to it:

setTimeout(timer, 1000);


Since timer is a function, you can pass it around like any other value.

Now, one might ask: "How do I call func with parameters?"

setTimeout(function() {
    func(something, somethingElse);
}, 1000);
//or
setTimeout(func, 1000, something, somethingElse);


About your actual code? it's fine. It's not the best piece of code I've ever, but it's not the worse as well. It's not too long for a timer, since all that's done is decrementing and calling itself again. I'd move the &lt; 10 checks to their own function, but maybe that's because I'm insane and not that "your way" is worse.


tl;dr Your code contains errors, but other than that, it's fine.