Randomblue
Randomblue

Reputation: 116293

setInterval("/*some code*/", time) and setInterval(function() { /*some code*/ }, time)

I was under the impression that

setInterval("/*some code*/", time)

was equivalent to

setInterval(function() {
   /*some code*/
}, time)

Apparently not! Please compare the following (full HTML):

<pre id=p><script>n=setInterval("for(n+=7,i=k,P='p.\\n';i-=1/k;P+=P[i%2?(i%2*j-j+n/k^j)&1:2])j=k/i;p.innerHTML=P",k=64)</script>

and

<pre id=p><script>n=setInterval(function() { for(n+=7,i=k,P='p.\\n';i-=1/k;P+=P[i%2?(i%2*j-j+n/k^j)&1:2])j=k/i;p.innerHTML=P },k=64)</script>

The two animations (the first being taken from here) are different.

Why are the two constructs not equivalent?

Answer: There are at least three differences

  1. Variable scope
  2. Performance
  3. String character escapes

Upvotes: 0

Views: 151

Answers (3)

jussinen
jussinen

Reputation: 688

I'm not sure I understand your examples but one of the main differences in between the two as far as I know is the setInterval(string, time) will be less performant than setInterval(function, time) as it will need to interpret the code on the fly, in the same way as eval(). Added to that, your code manipulates the Dom each time which is a performance hit.

As javascript is single threaded, the interval time in setInterval is not exact. See John Resig's post about that: http://ejohn.org/blog/how-javascript-timers-work/

I would expect results to be different based on the performance drain of setInterval(string, time) and the quite small interval.

Upvotes: 1

kevingessner
kevingessner

Reputation: 18985

Those two forms of setInterval are essentially equivalent -- but your code isn't. In the second example you're double-escaping your newline as \\n, instead of just \n. Try this:

<pre id=p><script>n=setInterval(function() { for(n+=7,i=k,P='p.\n';i-=1/k;P+=P[i%2?(i%2*j-j+n/k^j)&1:2])j=k/i;p.innerHTML=P },k=64)</script>

And that should be just like what you want.

The function() form of setInterval is better in a lot of ways -- it's more readable, and as you ran into here, you don't have to deal with trying to escape strings inside of string.

Upvotes: 3

T.J. Crowder
T.J. Crowder

Reputation: 1074495

I haven't studied the obfuscated code, but the difference between using a string and a function with setTimeout or setInterval is the scope in which the code is run. Also, when you use a string, some engines may not be able to optimize as well.

  • When you pass a string in, it's run at global scope.

  • When you pass a function in, it's run at the scope in which it's defined.

This affects which variables are in scope for the code, which can affect what it does.

Here's an un-obfuscated example: Live copy | source

(function() {
  var foo = 42;

  // This will say "undefined", because there is no global `foo`
  setTimeout("display(typeof foo);", 0);

  // This will say "number", because the function is closure over
  // the current scope, whcih *does* have `foo`
  setTimeout(function() {
    display(typeof foo);
  }, 0);

})();

function display(msg) {
  var p = document.createElement('p');
  p.innerHTML = String(msg);
  document.body.appendChild(p);
}

Upvotes: 6

Related Questions