Search code examples
javascriptsettimeout

Why does a callback in setTimeout have this == Window even in strict mode?


I am learning JS now and can not understand why 'use strict' directive does not work for a callback for setTimeout? As I know for use strict it should be undefined but always have global object.

function f() {
    'use strict'
    console.log(this === window)
}

function g() {
    console.log(this === window)
}

setTimeout(g,1000) // expect true, have true
setTimeout(f,1000) // expect false, have true


Solution

  • When setTimout() invokes a function in the browser, it sets the this to window. That is why it is not affected by strict mode - the this value is provided, instead of being left unset.

    The specification for setTimeout can be found in the HTML standard

    The timer initialization steps, given a WindowOrWorkerGlobalScope global, a string or Function handler, a number timeout, a list arguments, a boolean repeat, and optionally (and only if repeat is true) a number previousId, are:

    1. Let thisArg be global if that is a WorkerGlobalScope object; otherwise let thisArg be the WindowProxy that corresponds to global.

    [...]

    9. Let task be a task that runs the following substeps:

    1. If id does not exist in global's map of active timers, then abort these steps.

    2. If handler is a Function, then invoke handler given arguments with the callback this value set to thisArg. If this throws an exception, catch it, and report the exception.

    [...]

    In essence, the result is similar to calling the function like so:

    function f(){
     'use strict'
     console.log(this)
    }
    
    f.call(window)