0

I have not been able to find a proper explanation to this.

function subtract(x, y) {
    setTimeout(function(x, y) {
      document.write(x - y);
  }, 1000);
}

subtract(1, 1);

This writes NaN to the document because the x and y parameters passed to setTimeout are undefined. You'd think that x and y should be integer 1 and it's within scope of the subtract function. The following snippet works perfectly fine and writes integer 0 as expected:

function subtract(x, y) {
    setTimeout(function() {
      document.write(x - y);
  }, 1000);
}

subtract(1, 1);

Removing the parameters seem to solve the problem. Why?

bsb21
  • 45
  • 1
  • 8

3 Answers3

3

You have not passed the parameters to the function callback, when the callback is eventually invoked by the setTimeout the x and y are undefined.

So you see NaN as the output because undefined - undefined is NaN.

setTimeout takes the parameters of the function callback you have passed after the delay argument, in your case after 1000.

Without passing the parameters, the x and y variables is scoped to the function callback. It won't take the values from the outer scope as it is shadowed by the function parameters you have given.

function subtract(x, y) {
    setTimeout(function(x, y) {
      document.write(x - y);
  }, 1000, 1, 1);
}

subtract(1, 1);

You can also use Function.prototype.bind to pass the parameters to the callback function.

The bind takes the this context as the first argument and the rest of the arguments are the parameters to the function. In my example I have given null as the this context:

function subtract(x, y) {
    setTimeout(function(x, y) {
      document.write(x - y);
  }.bind(null,1,1), 500);
}

subtract(1, 1);
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
  • This should work, but IE9 and older (I know, really old) won't pass extra parameters to the callback. – Pointy May 08 '20 at 18:53
0

Its a javascript reference issue https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

Under -- The "this" problem section they mention the same issue

0

This is because of closures, asynchronous functions and execution context. settimeout is asynchronous function means it doesn’t wait or block the execution. Settimeout function get executed by eventloop tick. When you don’t pass arguments to function in it then it enclosed the values from subtract function and store it to use at the time of execution. This is because of concept of closures. In case if we pass arguments, it no longer behave like a closure and expect arguments at the time of execution which is null. So you get NaN. For experiment, pass default arguments to function in settimeout and check.

mjsid
  • 91
  • 1
  • 3