In bestehende Javascript-Funktionsaufrufe einklinken

Beim Web-Development hat man nicht immer die Möglichkeit an sämtlichem Javascript-Code eigene Änderungen vorzunehmen. Das kann daran liegen, dass man in einem bestehendem System nur beschränkten Zugriff hat, nur eine Kleinigkeit erweitern soll oder bestimmte Bibliotheken/Funktionen aktualisierbar bleiben soll. Bei mir war es heute mal wieder so weit.

Für einen Kunden setze ich eine Karte mit allen Projektstandorten mittels Google-Maps um. Gleichzeitig gibt es allerdings bereits eine bestehende Google-Maps-Einbindung, die eine Karte im Footer der Seite einbindet. Dabei kommt es zu einem Konflikt, weil das maps-script nur einmal eingebunden werden soll und danach genau eine callback-function aufruft. Bindet man die maps-scripte zweimal ein, weist uns google in der Entwicklerkonsole freundlich darauf hin das man unter solchen Umständen nicht korrekt arbeiten können. Das Google-Script darf also nur einmal eingebunden werden. Und kann dementsprechend auch nur eine callback-function angegeben werden.

Gehen wir von folgenden Bestands-Code aus:

var initiateMaps = function() { //this will be called by google
    initiateMyFooterMap();
}

Um auch noch eine Zweite Karte zu initialisieren müsste ich nun in der Funktion „initiateMaps“ eine zweite Funktion hinzufügen um meine Projekte-Karte zu laden. Das geht allerdings nicht, weil ich keinen direkten Zugriff auf diesen Code habe. Wie kann ich mich nun in diese bestehende Funktion zum Aufruf der Google-Maps API einklinken?

Die Lösung

Mit folgendem Code können wir die bestehende Funktion überschreiben und um eigene Anweisungen ergänzen. Wichtig ist, das dieser Code nach der bestehenden Funktions-Definition ausgeführt werden muss:

if(initiateMaps===undefined) {//just a check
    console.log('inititeMaps is not defined yet');
}

var old_initiateMaps = initiateMaps;
initiateMaps = function() {
    old_initiateMaps.apply(this,arguments);//this will call the previous function
    initiateMyProjectMap();//this will addional call my new functionalities
}

Mittels fn.apply() kann die alte Funktion aufgerufen und mit Parameter bestückt werden. Davor oder danach lässt sich nun eigener Code ausführen. Es wird sozusagen eine „hook“ eingebaut.

Mozilla nennt diese Lösung das „monkey patching“ (zu finden in der Dokumentation von apply). Dem Namen nach offensichtlich keine besonder rühmliche Art Code zu schreiben. Ganz klar, bei übermäßigem Gebrauch führt monkey patching zu Würgereflexen bei Entwicklern. Code-Struktur und Programmabläufe werden dann immer schwerer zu lesen und somit auch schwer zu warten.

Dosiert eingesetzt und gut dokumentiert, ermöglicht diese Lösung aber, dass Anreichern bestehender Funktionalität ohne die Updatefähigkeit des bestehenden Codes zu gefährden. Und das ist ja dann schon ziemlich gut.