Is There Ever a Good Reason to Pass a String to Settimeout

Is there ever a good reason to pass a string to setTimeout?

You can always use global variables by accessing them as properties of the window object, like window.globalVar (though using globals is indeed not a good practice), so no, I don't think there is ever a good reason to use the deprecated syntax.

It is probably allowed for historical reasons: as Felix Kling mentioned, the original syntax did only allow to pass a string of code:

Introduced with JavaScript 1.0, Netscape 2.0. Passing a Function object reference was introduced with JavaScript 1.2, Netscape 4.0; supported by the MSHTML DOM since version 5.0. [source, my emphasis]

If browsers don't support the use of a string as first argument to setTimeout and setInterval anymore, there will be lots of code on the internet that doesn't function anymore.

SetTimeout - why is passing a function better then a string?

There are a couple of reasons.

  1. Primarily, when you pass setTimeout a string, the string is evaluated in the global context. That means that the function it calls has to be a global function. Avoiding globals is good practice.

    For instance, this fails: Live Example (see error in the console)

    (function() {
    "use strict";

    setTimeout("display('hi');", 0);

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

    ...because display is not a global function.

    But this works: Live Example

    (function() {
    "use strict";

    setTimeout(display.bind(null, 'hi'), 0);
    // Or:
    // setTimeout(function() { display('hi'); }, 0);

    function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = String(msg);
    document.body.appendChild(p);
    }
    })();
  2. Using a function reference rather than a string means we're using the same semantics we use just about everywhere else we use callbacks, rather than making calling setTimeout some weird special thing. For instance, the way I give addEventListener a function to call when an event occurs is the same way I give setTimeout a function to call when it times out. Consistent semantics help to avoid errors.

  3. Using a function reference rather than a string lets me be very specific about what function I'm calling. Consider:

    function showInASecond(str) {
    setTimeout(function() {
    alert(str);
    }, 1000);
    }

    I couldn't reasonably use a string there. Oh, I could try to create a concatenation, being sure to escape everything I'd have to escape in the str (like quotes, backslashes, and such), but simple is better.

  4. If you pass setTimeout a string, it has to fire up a full JavaScript parser to evaluate it. Not much of an issue, but still more work than required.

Is it bad practice to pass a string to settimeout? If yes, why?

Yes, it is.

The string must be eval'd, which is evil (and very slow).

It also prevents you from using local variables in the callback.

How can I pass a parameter to a setTimeout() callback?

setTimeout(function() {
postinsql(topicId);
}, 4000)

You need to feed an anonymous function as a parameter instead of a string, the latter method shouldn't even work per the ECMAScript specification but browsers are just lenient. This is the proper solution, don't ever rely on passing a string as a 'function' when using setTimeout() or setInterval(), it's slower because it has to be evaluated and it just isn't right.

UPDATE:

As Hobblin said in his comments to the question, now you can pass arguments to the function inside setTimeout using Function.prototype.bind().

Example:

setTimeout(postinsql.bind(null, topicId), 4000);

why we are using quotes inside a parameter for a function in javascript?

The reason that your code is calling Redirect() immediately is because it gets evaluated when setTimeout is run.

What you can do to mitigate that is to pass an anonymous function to wrap around the method. Like so: setTimeout(function(){ Redirect(); }, 10000);

This link explains why your string "Redirect()" is evaluated as you'd expect. In short (taken from the link): String literals are evaluated in the global context, using eval.
WindowTimers.setTimeout()

setTimeout() doesn't allow me to pass text values

Do this:

setTimeout(function() { loadPHPQuote(code); }, 1000);
  • When you use quotes, it calls eval behind the scene,
  • when you need to pass arguments wrap it in a function like above.
  • To prevent calling function immediately, don't use () in setTimeout or setInterval directly

Why is the method executed immediately when I use setTimeout?

You're calling the function immediately and scheduling its return value.

Use:

setTimeout(testFunction, 2000);
^

Notice: no parens.

JavaScript setTimeout in Object

setTimeout takes a reference to a function. The code you have is calling the function.

This should be changed to:

var object = 
{
'name' : 'user',
'limit' : function()
{
setTimeout(function() { destroyMe(this); }, 10000);
}
}

(You may have issues using this in this context, try it!)

var object = 
{
'name' : 'user',
'limit' : function()
{
setTimeout( function() { console.log("dd"); },3000);
}
}

Why is setTimeout(fn, 0) sometimes useful?

In the question, there existed a race condition between:

  1. The browser's attempt to initialize the drop-down list, ready to have its selected index updated, and
  2. Your code to set the selected index

Your code was consistently winning this race and attempting to set drop-down selection before the browser was ready, meaning that the bug would appear.

This race existed because JavaScript has a single thread of execution that is shared with page rendering. In effect, running JavaScript blocks the updating of the DOM.

Your workaround was:

setTimeout(callback, 0)

Invoking setTimeout with a callback, and zero as the second argument will schedule the callback to be run asynchronously, after the shortest possible delay - which will be around 10ms when the tab has focus and the JavaScript thread of execution is not busy.

The OP's solution, therefore was to delay by about 10ms, the setting of the selected index. This gave the browser an opportunity to initialize the DOM, fixing the bug.

Every version of Internet Explorer exhibited quirky behaviors and this kind of workaround was necessary at times. Alternatively it might have been a genuine bug in the OP's codebase.


See Philip Roberts talk "What the heck is the event loop?" for more thorough explanation.



Related Topics



Leave a reply



Submit