Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"this" in global functions

I was under the impression that the "this" keyword represents the current owner that is in scope. Obviously, this is wrong. Let me get to the code:

alert(this);     // alerts as [object Window] -- Okay

function p1() {
    alert(this);
}

var p2 = function() {
    alert(this);
}

p1();           // alerts as undefined  -- ???
p2();           // alerts as undefined  -- ??
window.p1();    // alerts as [object Window] -- Okay
window.p2();    // alerts as [object Window] -- Okay

The code above first alerts [object Window], as I would expect but then the next two calls to p1() and p2() alert "this" as "undefined". The final two calls to p1() and p2() alert "this" as [object Window].

Isn't it the case that p1() and p2() exist in the global (i.e., window) scope? I thought that calling window.p1() is synonymous with calling p1(), just like calling alert() is synonymous with window.alert().

To my (C#) way of thinking, p1() and p2() are in the global scope. These functions are members of the global window object so when they refer to "this" they should be referring to [object Window]. Obviously, I'm very wrong here.

like image 442
Tom Baxter Avatar asked Jul 10 '15 12:07

Tom Baxter


2 Answers

Becasue you are using strict mode and as per the spec:

If this is evaluated within strict mode code, then the this value is not coerced to an object.

The code you have does alert window in all instances of alert, but because you are in strict mode, it is undefined (as it should be)

UPDATE: chrome dev tools alerts window not undefined, however if you wrap it in a self executing function you get undefined as expected

(function(){
   'use strict';
   alert(this);
}());
like image 102
atmd Avatar answered Sep 29 '22 14:09

atmd


When you call a function like foo(), then the value of this depends on whether the code runs in strict mode or not (the default actually).

In strict mode, this will be undefined (as you already found out).

In "loose mode" this will indeed refer to window, but that's not because the functions are global, i.e. "owned" by the global scope. You get the same behavior for local functions:

(function() {
  function foo() {
    console.log(this); // logs the window object, but `foo` is not global
  }
  foo();
}());

This is simply an explicitly defined behavior:

  1. If the function code is strict code, set the ThisBinding to thisArg.
  2. Else if thisArg is null or undefined, set the ThisBinding to the global object.
  3. Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg). ...

As you can see, in "loose" mode, if thisArg is undefined, which is the case if you call the function "normally" as foo(), then it will be set to window explicitly.

like image 42
Felix Kling Avatar answered Sep 29 '22 14:09

Felix Kling