Search code examples
javascriptclosuressettimeoutinfinite-loop

Uncaught TypeError: X is not a function. While using javascript closure


I'm playing with JavaScript and see following error in console:

Uncaught TypeError: div is not a function.

function getRandomColor() {
    var letters = '0123456789ABCDEF';
    var color = '#';
    for (var i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
}

function createDiv(interval) {
    let radius = 300;
    let int = interval;
    var f = 0;
    var s = 2 * Math.PI / 180;
    let timerId = window.setTimeout(function tick()
    {
        var div = document.createElement('div');
        div.className = 'circle';
        div.style.backgroundColor = getRandomColor();
        div.style.left = (radius + radius * Math.cos(f)) + 'px';
        div.style.top = (radius + radius * Math.sin(f)) + 'px';
        document.body.appendChild(div);
        f += s;
        setTimeout(tick, int);
    }, int)

}

let div = createDiv(10);
div(); 

I left the following for simplicity:

function createDiv(interval) {
    let timerId = window.setTimeout(function tick()
    {
        setTimeout(tick, 10);
    }, 10)
}

let div = createDiv(10);
div();

This is essentially an infinite loop. And error occurs when calling div() but loop is working.

What is wrong? And how it fix?


Solution

  • There is no closure here: you're calling a function that returns undefined and attempting to call undefined() as if it were a function. Simply call your function like createDiv(10);. Note that I've added a height and width to your div so the result is visible.

    function getRandomColor() {
      var letters = '0123456789ABCDEF';
      var color = '#';
      for (var i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 16)];
      }
      return color;
    }
    
    function createDiv(interval) {
      let radius = 300;
      let int = interval;
      var f = 0;
      var s = 2 * Math.PI / 180;
      let timerId = window.setTimeout(function tick() {
        var div = document.createElement('div');
        div.className = 'circle';
        div.style.backgroundColor = getRandomColor();
        div.style.height = div.style.width = "50px";
        document.body.appendChild(div);
        f += s;
        setTimeout(tick, int);
      }, int)
    }
    
    createDiv(1000);