JavaScript-Klassen nachträglich ändern

Verhalten von Objekten ändern, auf deren Klassendefinition offiziell kein Zugriff besteht

Bei der Arbeit an Web-Projekten und/oder mit Node.js kann es immer wieder mal vorkommen, dass Funktionalität bestehender Objekte geändert oder ergänzt werden soll, aber man keinen Zugriff auf die ursprüngliche Klassendefinition hat, etwa, weil sie in einer gekapselten Funktion vorliegt. Die einfachste Möglichkeit ist natürlich, die Ursprungsklasse selbst anzupassen, aber das ist nicht immer erwünscht. Ich zeige hier in einem Schnipsel eine Möglichkeit, den Prototypen selbst zu ändern.

Nehmen wir an, irgendwo ist folgende einfache Klasse definiert:

function TestObj(val) {
	this.val = val;
}

TestObj.prototype.get = function () {
	return '"' + this.val + '"';
}

Nun können wir zwei Variablen definieren und die Methode verwenden:

var test1 = new TestObj('FOO'), test2 = new TestObj('BAR');

console.log(test1.get(), test2.get());
// Ausgabe:
// "FOO" "BAR"

Solange man Zugriff auf die Funktionsklasse TestObj hat, kann man genau wie oben mittels TestObj.prototype weitere Funktionalität hinzufügen oder ändern. Was aber, wenn diese z.B. in einer Wrapper-Funktion liegt und eben nicht erreichbar ist?

ECMAScript erlaubt mittels des Konstrukts Object.getPrototypeOf(var) (ecma-262 15.2.3.2) den Zugriff auf den ursprünglichen Prototyp, aus dem das Objekt entstanden ist. Im Sprachgebrauch von klassenorientierten Sprachen wäre das die ursprüngliche Klasse, deren Instanz gerade verwendet wird.

Mittels dieses Prototype-Objekts ist es dann einfach, die Funktionalität der Klasse und damit auch aller bereits bestehenden Objekte zu ändern:

var proto = Object.getPrototypeOf(test1)

proto.old_get = proto.get;
proto.get = function () {
	return "\n>>> " + this.old_get();
}

console.log(test1.get(), test2.get());
// Ausgabe:
// >>> "FOO"
// >>> "BAR"

Ich hoffe, damit einen Ansatz geliefert zu haben, wie man z.B. Verhalten von JQuery-Plugins ändern kann, ohne den Quelltext dieser „hacken“ zu müssen.

Flattr