Vorsicht mit dem «Klonen» von Variablen

Mischa Sameli, Geschäftsführer & Leiter Entwicklung

Immer wieder kommt es vor, dass Variablen nicht den Wert enthalten, den wir eigentlich erwarten. In der Regel kommt das davon, dass der Scope nicht genau definiert ist, in welchem sich die Variable befindet. Nicht immer liegts aber am fehlenden Scope, wie ich an folgendem Beispiel zeigen möchte.

Immer wieder kommt es vor, dass Variablen nicht den Wert enthalten, den wir eigentlich erwarten. In der Regel kommt das davon, dass der Scope nicht genau definiert ist, in welchem sich die Variable befindet. Nicht immer liegts aber am fehlenden Scope, wie ich an folgendem Beispiel zeigen möchte.
a.name = #a.name#
b.name = #b.name#
So, normalerweise würde man nun davon ausgehen, dass in der Variable a.name der Wert hans abgelegt ist und in der variable b.name der Wert peter. Leider nein, heisst die Antwort, die ja zu erwarten war. Beide Variablen haben den Wert hans. Denn: b ist nur eine Referenz zu a, aber keine Kopie. Da name in a schon definiert ist, kann er in b nicht überschrieben werden. Was passiert nun, wenn die die Referenz b um eine Variable erweitern?

1<cfset b.anrede = "Herr">
Ist nun b.anrede definiert oder gibts das gar nicht, weil anrede in a nicht vorkommt? Anrede ist definiert, und zwar sowohl in a und in b und zwar beide Male mit dem Wert Herr. Nun erbt also a die Eigentschaft von b – ungefragt und natürlich auch unbemerkt. Und was, wenn wir nun auch a die anrede hinzufügen?
1<cfset a.anrede = "Frau">
Klar, nun erhält auch b die anrede Frau – ebenso unbemerkt und ungefragt, weil ja b nur eine Referenz zu a ist. Der Teufel steckt also im Detail. Und hier nützt das beste Scoping-Verhalten nichts. Die einzige Methode ist in diesem Moment, die Struktur a zu kopieren:
1<!--- Struktur anlegen --->
2<cfset a = StructNew()>
3<cfset a.name = "hans">
4<!--- Kopie der Struktur anlegen für andere arbeiten --->
5<cfset b = Duplicate(a)>
6<cfset b.name = "peter">
7<!--- und dann geben wir die beiden Namen einmal aus --->
8<cfoutput>
9a.name = #a.name#<br />
10b.name = #b.name#<br />
11</cfoutput>
Und wer hat diese Funktion schon einmal benützt?