Javascript

Difference between setTimeout with a string argument and with a non-string argument

19 September 2026 · 11 min read

Difference between setTimeout with a string argument and with a non-string argument

Understanding the nuances of JavaScript’s setTimeout function is crucial for writing efficient and maintainable code. One common point of confusion arises when considering the difference between setTimeout with a string argument and with a non-string argument. While both achieve delayed execution, their behavior and implications for security and performance diverge significantly. In this article, we will delve deep into these differences, exploring the underlying mechanisms, potential pitfalls, and best practices for using setTimeout effectively. We’ll examine the security risks associated with using string arguments, compare the performance implications, and provide practical examples to illustrate the concepts. Mastering these distinctions will not only enhance your JavaScript skills but also help you write more robust and secure applications. Let’s explore how to delay function execution safely and efficiently using setTimeout.

Understanding setTimeout: The Basics

setTimeout is a fundamental JavaScript function used to execute a function or evaluate an expression after a specified delay. The function takes two primary arguments: the function or code to be executed and the delay time in milliseconds. For example, setTimeout(myFunction, 1000) would execute myFunction after a delay of one second. It’s essential to understand that setTimeout doesn’t pause the execution of the script; instead, it schedules the execution of the provided function or code to occur in the future, allowing the rest of your code to continue running without interruption. This asynchronous behavior is a cornerstone of JavaScript’s non-blocking nature and is crucial for creating responsive and interactive web applications.

The core functionality of setTimeout relies on the browser’s event loop, which manages the execution of tasks and events. When setTimeout is called, the browser adds the function or code to a queue and waits for the specified delay before executing it. During this time, the main thread remains free to handle other events, such as user interactions or network requests. Once the delay has elapsed, the function or code is moved from the queue to the call stack and executed. This mechanism ensures that long-running tasks don’t block the main thread, preventing the browser from becoming unresponsive.

It’s also important to note that the delay specified in setTimeout is not a guaranteed execution time. The actual execution may be delayed further if the main thread is busy with other tasks. However, the browser will attempt to execute the function or code as soon as possible after the specified delay. Therefore, while setTimeout provides a way to schedule tasks for future execution, it’s not a precise timer and should not be relied upon for time-critical operations. Asynchronous programming and understanding the event loop are key to mastering JavaScript’s capabilities. Using JavaScript effectively involves understanding how to manage delays.

String Argument vs. Function Argument: A Critical Difference

The most significant difference between setTimeout with a string argument and with a non-string argument lies in how the code to be executed is represented. When you pass a string to setTimeout, JavaScript uses the eval() function behind the scenes to execute that string as code. This approach has several drawbacks, including security risks and performance issues. On the other hand, when you pass a function directly to setTimeout, the function is executed directly without invoking eval(). This method is generally considered safer, more efficient, and more aligned with modern JavaScript best practices. Understanding this distinction is crucial for writing secure and performant JavaScript code. Using a function argument is the preferred method.

The use of string arguments with setTimeout opens the door to potential security vulnerabilities, particularly if the string contains user-supplied data. Because eval() can execute arbitrary code, a malicious user could inject harmful code into the string, leading to cross-site scripting (XSS) attacks or other security breaches. For example, if the string argument is constructed using data from a form field, an attacker could inject JavaScript code into the form field, which would then be executed by setTimeout when the timer expires. This type of vulnerability can be difficult to detect and can have serious consequences for the security of your application. Therefore, it’s essential to avoid using string arguments with setTimeout, especially when dealing with user-supplied data.

From a performance perspective, using a string argument with setTimeout is generally less efficient than using a function argument. When a string argument is passed, JavaScript needs to parse and compile the string before executing it, which adds overhead to the execution process. In contrast, when a function is passed directly, JavaScript can execute the function directly without any additional parsing or compilation. This difference in performance can be noticeable, especially when setTimeout is used frequently or with complex code. Furthermore, using a function argument allows JavaScript engines to optimize the code more effectively, leading to further performance improvements. According to Mozilla, “Using strings is generally discouraged for performance and security reasons.” [1]

Security Implications: Why Strings Are Risky

As mentioned earlier, using string arguments with setTimeout can introduce significant security risks, primarily due to the use of eval(). The eval() function allows you to execute arbitrary code, which can be exploited by attackers to inject malicious code into your application. This is particularly concerning when the string argument contains user-supplied data, as it opens the door to XSS attacks. In an XSS attack, an attacker injects malicious scripts into a website, which are then executed by the victim’s browser. This can allow the attacker to steal sensitive information, such as cookies or login credentials, or to perform actions on behalf of the victim.

To illustrate the potential security risks, consider the following example:

let userInput = "<script>alert('XSS Attack!');</script>"; setTimeout("eval(userInput)", 1000); 

In this case, the userInput variable contains a malicious script that displays an alert box. When this code is executed, the alert box will be displayed, demonstrating the potential for an attacker to inject arbitrary code into your application. While this is a simple example, more sophisticated attacks can be much harder to detect and can have more serious consequences. Therefore, it’s crucial to avoid using string arguments with setTimeout and to sanitize any user-supplied data before using it in your application.

To mitigate these security risks, it’s always recommended to use function arguments with setTimeout instead of string arguments. When you pass a function directly, JavaScript executes the function without using eval(), eliminating the risk of code injection. Additionally, you should always sanitize any user-supplied data before using it in your application. Sanitization involves removing or encoding any potentially malicious characters or code, ensuring that the data cannot be used to execute arbitrary code. By following these best practices, you can significantly reduce the risk of security vulnerabilities in your application. OWASP (Open Web Application Security Project) provides valuable resources on preventing XSS attacks. [2]

Performance Considerations: Function Arguments Excel

Beyond security, performance is another key factor to consider when choosing between string and function arguments with setTimeout. As mentioned earlier, using a string argument is generally less efficient than using a function argument. This is because JavaScript needs to parse and compile the string before executing it, which adds overhead to the execution process. In contrast, when a function is passed directly, JavaScript can execute the function directly without any additional parsing or compilation. This difference in performance can be noticeable, especially when setTimeout is used frequently or with complex code. Proper use of setTimeout significantly affects application responsiveness.

The performance difference between string and function arguments can be attributed to the way JavaScript engines optimize code. When a function is passed directly to setTimeout, the engine can optimize the function for execution, potentially caching the compiled code for future use. This can lead to significant performance improvements, especially when the same function is executed multiple times. In contrast, when a string argument is passed, the engine needs to parse and compile the string every time it’s executed, preventing it from applying the same optimizations. This can result in slower execution times and increased resource consumption.

To illustrate the performance difference, consider a scenario where you need to execute a complex calculation repeatedly after a short delay. Using a function argument would allow the JavaScript engine to optimize the calculation for execution, leading to faster execution times and reduced resource consumption. On the other hand, using a string argument would prevent the engine from applying these optimizations, resulting in slower execution times and increased resource consumption. Therefore, for performance-critical applications, it’s always recommended to use function arguments with setTimeout. According to Google’s Web Fundamentals, optimizing JavaScript execution is vital for web performance. [3]

Best Practices and Alternatives

When working with setTimeout, sticking to best practices ensures clean, efficient, and secure code. Avoiding string arguments is paramount due to the security and performance implications we’ve discussed. Instead, always pass a function reference directly to setTimeout. This practice eliminates the risks associated with eval() and allows JavaScript engines to optimize the code more effectively. Here are some concrete steps to follow:

  1. Always use function arguments: Pass a function reference directly to setTimeout instead of a string.
  2. Sanitize user input: If you must use user-supplied data, always sanitize it to prevent code injection.
  3. Use setInterval with caution: Be aware that setInterval can lead to unexpected behavior if the code being executed takes longer than the specified interval.
  4. Consider using Promises and async/await: For more complex asynchronous operations, consider using Promises and async/await to improve code readability and maintainability.

In modern JavaScript development, Promises and async/await offer powerful alternatives to traditional callback-based asynchronous programming. Promises provide a cleaner and more structured way to handle asynchronous operations, making code easier to read and maintain. Async/await simplifies the syntax of Promises, allowing you to write asynchronous code that looks and behaves more like synchronous code. These features can be particularly useful when dealing with complex asynchronous workflows involving multiple setTimeout calls. Consider the following example:

async function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function doSomething() { console.log("Starting..."); await delay(1000); console.log("After 1 second..."); await delay(2000); console.log("After 3 seconds..."); } doSomething(); 

This code uses Promises and async/await to create a delay function that can be used to pause the execution of an asynchronous function. This approach is more readable and maintainable than using nested setTimeout calls. While setTimeout has its place, understanding and utilizing modern alternatives can significantly improve your code quality. Using function arguments instead of strings is a core principle.

  • Favor function arguments over string arguments.

  • Sanitize all user-provided data rigorously.

  • Leverage Promises and async/await for cleaner asynchronous code.

  • Be mindful of potential issues with setInterval.

Infographic here
FAQ ---
What is the main difference between using a string and a function in setTimeout?
The main difference is that using a string argument causes `setTimeout` to use `eval()` behind the scenes, which can lead to security vulnerabilities and performance issues. Using a function argument executes the function directly, avoiding these problems.
Is it always bad to use a string in setTimeout?
Yes, it is generally considered bad practice to use a string in `setTimeout` due to the security and performance implications. There are very few, if any, valid use cases for it.
How can I avoid using a string in setTimeout?
Simply pass a function reference directly to `setTimeout` instead of a string. For example, instead of `setTimeout("myFunction()", 1000)`, use `setTimeout(myFunction, 1000)`.
What are the alternatives to setTimeout?
Alternatives to `setTimeout` include `setInterval` (for repeated execution), Promises, and async/await (for more structured asynchronous programming).
In summary, the **difference between setTimeout with a string argument and with a non-string argument** boils down to security, performance, and maintainability. Using function arguments is the clear winner in all these aspects. By embracing this best practice and leveraging modern JavaScript features like Promises and async/await, you can write safer, more efficient, and more maintainable code. The choice is clear: prioritize function arguments for a more robust and secure coding experience. Now, take **Question & Answer :**

I am learning JavaScript and I have learned recently about JavaScript timing events. When I learned about setTimeout at W3Schools, I noticed a strange figure which I didn’t run into before. They are using double quotes and then call the function.

Example:

setTimeout("alertMsg()", 3000); 

I know that double and single quotes in JavaScript means a string.

Also I saw that I can do the same like that:

setTimeout(alertMsg, 3000); 

With the parentheses it’s referring, without the parentheses it’s copied. When I am using the quotes and the parentheses it’s getting crazy.

I will be glad if someone can explain to me the difference between these three ways of using setTimeout:

With the parentheses:

setTimeout("alertMsg()", 3000); 

Without the quotes and the parentheses:

setTimeout(alertMsg, 3000); 

And the third is only using quotes:

setTimeout("alertMsg", 3000); 

N.B.: A better source for setTimeout reference would be MDN.

Using setInterval or setTimeout

You should pass a reference to a function as the first argument for setTimeout or setInterval. This reference may be in the form of:

  • An anonymous function

    setTimeout(function(){/* Look mah! No name! */},2000); 
    
  • A name of an existing function

    function foo(){...} setTimeout(foo, 2000); 
    
  • A variable that points to an existing function

    var foo = function(){...}; setTimeout(foo, 2000); 
    

    Do note that I set “variable in a function” separately from “function name”. It’s not apparent that variables and function names occupy the same namespace and can clobber each other.

Passing arguments

To call a function and pass parameters, you can call the function inside the callback assigned to the timer:

setTimeout(function(){ foo(arg1, arg2, ...argN); }, 1000); 

There is another method to pass in arguments into the handler, however it’s not cross-browser compatible.

setTimeout(foo, 2000, arg1, arg2, ...argN); 

Callback context

By default, the context of the callback (the value of this inside the function called by the timer) when executed is the global object window. Should you want to change it, use bind.

setTimeout(function(){ this === YOUR_CONTEXT; // true }.bind(YOUR_CONTEXT), 2000); 

Security

Although it’s possible, you should not pass a string to setTimeout or setInterval. Passing a string makes setTimeout() or setInterval() use a functionality similar to eval() that executes strings as scripts, making arbitrary and potentially harmful script execution possible.