JavaScript „this“ im Bezug auf Methoden und Objekte

Nach meinem Artikel über die Gleichheitsoperatoren in Javascript möchte ich über den kleinen Ausdruck this in JavaScript schreiben. Oft benutzt, aber kaum jemandem komplett bekannt.

Methoden und Funktionen

In diesem Artikel wird es oft um einen Bezug auf Methoden oder auf Funktionen gehen. Deswegen zunächst zur Definition – Methoden sind im ECMAScript als folgendes definiert:

A method is a [..] function that is the value of a property.

NOTE: When a function is called as a method of an object, the object is passed to the function as its this value.

Man kann also sagen, dass Funktionen standard-Subroutinen in einer Anwendung darstellen. Methoden dagegen sind Eigenschaften von Objekten, die als Funktionen angesprochen werden.

Anwendung im Kontext

Bezugnehmend auf die ECMAScript 5.1 – Spezifikation ist eine ausführbare Anwendung eine Ansammlung von vielen ausführbaren Kontexten. Diese Kontexte unterstützen die sprachlichen Konstrukte, die wir benötigen um die Anwendung zu planen und um so Variablen und Funktionen innerhalb des Programms voneinander abzugrenzen.

Weitere Informationen zu der Thematik des ausführbaren Kontextes enthält die schon angeführte ECMAScript-Spezifikation im Abschnitt Execution Contexts. Im Folgenden interessieren wir uns für den Inhalt der this-Variable an verschiedenen Orten und wie dieser bestimmt wird.

Der globale Kontext und die Konstruktoren

Wir versuchen als erstes den folgenden Code im Browser oder in Node.js auszuführen:

function add(foo, bar) {
  console.log(this);
  return foo + bar;
}

add(1, 1);

Durch den globalen Kontext wird die Zeile zwei als global in Node oder window im Browser ausgeben. Wird nach der Funktionsdefinition in Zeile #1 'use strict' eingefügt, wird this – im Browser sowie auch unter node.js – zu undefined.

Nun überlegen wir was passiert wenn stattdessen ein Konstruktor aufgerufen wird:

Sagen wir wir haben ein Shape()-Objekt. In dem Shape-Konstruktor als Ergebnis von new Shape(), verweist this auf das aktuelle Objekt. Dies muss immer im Hinterkopf bleiben wenn wir objektorientierten Code schreiben. Wenn eine Funktion als Methode eines Objekts aufgerufen wird, oder wenn new genutzt wird, dann wird der Wert von this zur lokalen Instanz des Objekts, ansonsten referenziert this zum globalen Kontext (oder wie wir oben gesehen haben bei 'use strict' zu undefined).

Oft gemachte Fehler

Gut aufpassen sollte man bei eingeschlossene Funktionen innerhalb von Methoden. Schauen wir uns folgendes Beispiel an und überlegen uns den Wert von this innerhalb checkBounds():

function Shape() {
  this.x = 0;
  this.y = 0;
}

Shape.prototype = {
  move: function(x, y) {
    this.x += x;
    this.y += y;

    function checkBounds() {
      if (this.x > 100) {
        console.error('Warning: Shape out of bounds');
      }
    }

    checkBounds();
  }
};

var shape = new Shape();
shape.move(101, 1);

Zwar ist die checkBounds()-Funktion innerhalb der move()-Methode definiert, jedoch wird die console.log() – Zeile niemals erreicht werden, da der Wert von this zum Globalen Kontext referenziert.

Laut Spezifikation ist es so erlaubt, jedoch eine nicht wirklich lesbare Schreibweise – zumindest kann man damit Anfänger sehr leicht von der Strecke bringen, aber auch leicht Fehler in seinen Code hauen 😉 – also aufpassen!

Sicherer ist es da, this einfach einer anderen Variable zuzuordnen.

Shape.prototype = {
  move: function(x, y) {
    var self = this;

    this.x += x;
    this.y += y;

    function checkBounds() {
      if (self.x > 100) {
        console.error('Warning: Shape out of bounds');
      }
    }

    checkBounds();
  }
};

Nun referenziert self zur eigenen Methode und so kann this in der eingeschlossenen Funktion weiterverwendet werden.

self kann man dabei nennen wie man will, es ist kein reserviertes Wort, allerdings heben manche Editoren mit Syntax Highlighting self schön hervor.

Fazit

Zusammengefasst können wir also sagen, dass wir, wenn wir mit this arbeiten, folgendes beachten sollten:

  • der Wert ändert sich mit dem Aufruf der Funktion: wird new myConstructor() oder myConstructor.method() benutzt, so referenziert es auf die Instanz, ansonsten auf den globalen Kontext,
  • wird 'use strict' benutzt, so wird this innerhalb von Funktionen zu undefined,
  • jede Variable kann auf this zeigen, ein typischer Name dafür ist self.

Wer weitere Informationen zu dem Thema sucht, kann in meiner favorisierten ECMAScript-Doku unter den Punkten global codeexecuting eval code und entering functions alles Weitere finden.

Flattr this!

3 Kommentare

  1. Interessanter Artikel! Selbes Verfahren mit der this-Komponente verwende ich bei der Android-Programmierung und anonymen Klassen. Wenn ich da den aktuellen Kontext übergeben möchte, geht das ebenfalls nicht mit this, sondern ich muss vor dem Erstellen der anonymen Klasse this zwischenspeichern.

    Habe deinen Blog mal in meinen Lesezeichen-Ordner „Blogs“ gepackt. 😉

    Antworten

    1. Vielen Dank Miguel! Darf ich das ebenfalls bei dir auch machen? Es gibt zwar genug IT-Blogs, wenn man allerdings auch den privaten Bezug zu den Machern hat, ist das ja wieder etwas anderes.. 😉

      Antworten

      1. Klar! Momentan ist mein Blog (btw. alle meine Webprojekte) gerade offline, da ich bei united-domains ausgezogen bin und ich mir jetzt einen Linux-basierten Web/FTP/Database Server (vServer) aufsetze. Da spare ich eine menge Geld^^

        Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.