lokale Variablen im Konstruktor
Danny Raufeisen
- javascript
1 Cheatah0 molily-1 Danny Raufeisen1 Houyhnhnm0 Danny Raufeisen0 Struppi
0 wahsaga1 molily
Hallo.
Wie erklärt es sich, dass man in JavaScript folgendes machen kann:
code:
function MeinConstructor ()
{
var lokaleVar = "Inhalt der Lokalen";
this.func = function ()
{
alert(lokaleVar);
}
}
x = new MeinConstructor ()
x.func ();
var lokaleVar müsste doch, da sie eine lokale Variable der Funktion MeinConstructor() ist, nach Rückkehr von der Konstruktor-Funktion nicht mehr vorhanden sein. Trotzdem ist sie bei ausführen von x.func (); ja noch zugänglich. Wie kann das sein? Wie ist das intern erklärt?
mfg
Danny Raufeisen
Hi,
var lokaleVar müsste doch, da sie eine lokale Variable der Funktion MeinConstructor() ist, nach Rückkehr von der Konstruktor-Funktion nicht mehr vorhanden sein.
nur weil Du ein Objekt "MeinConstructor" nennst, ist es noch lange kein Konstruktor, sondern bleibt Objekt. Entsprechend bleiben auch die objektlokalen Variablen erhalten, solange das instanziierte Objekt existiert.
Cheatah
Hallo,
var lokaleVar müsste doch, da sie eine lokale Variable der Funktion MeinConstructor() ist, nach Rückkehr von der Konstruktor-Funktion nicht mehr vorhanden sein. Trotzdem ist sie bei ausführen von x.func (); ja noch zugänglich. Wie kann das sein? Wie ist das intern erklärt?
Private Eigenschaften werden halt so notiert, und func ist eine priviligierte Methode mit Zugriff auf die private Eigenschaft.
http://www.crockford.com/javascript/private.html
Mathias
function MeinConstructor ()
{
var lokaleVar = "Inhalt der Lokalen";this.func = function ()
{
alert(lokaleVar);
}
}x = new MeinConstructor ()
x.func ();
Ich möchte einfach nur durchblicken, wie das funktioniert, sonst nichts. Ich deklariere lokaleVar, diese ist nirgendwo anders als innerhalb des Codeblocks von MeinConstructor () zugänglich. Und doch kann ich sie noch später in einer nested function bei x.func(); erreichen. Was denkt sich denn der Interpreter dabei? Woher weiß er, dass lokaleVar noch beibehalten werden soll? Mich interessiert doch nur, wie das intern funzt.
mfg
Danny Raufeisen
Javascript ist keine blockorientierte Sprache im klassischen Sinn.
Wenn Du schreibst:
a = new MyObject;
wird ein Objekt erzeugt, das u.a. die Variablen enthält, die Du innerhalb von MyObject per var oder mit this.variablenname definiert hast.
Das Objekt ist so lange gültig, wie es Referenzen darauf gibt.
Das bedeutet, daß ein einfacher Funktionsaufruf ein Objekt erzeugt, das so lange gültig ist, wie der Funktionsaufruf aktiv ist; danach existieren keine Referenzen auf das Objekt mehr - Du kannst die 'Leiche' also nicht mehr erreichen und der Garbage-Collector von JS vernichtet es.
Wenn man schreibt:
a = new MyObject;
wird die Funktion MyObject - man spricht in diesem Zusammenhang von einem Konstruktor - aufgerufen und eine Referenz auf das Objekt, das bei dem Aufruf erzeugt wurde, wird an die Variable a zugewiesen; nachdem MyObject terminiert hat, existiert also noch eine Referenz auf das Objekt; der Garbage-Collector läßt es unberührt.
Über a.variablenname kannst Du hinterher noch den Wert von variablenname abfragen oder Funktionen aufrufen, die in MyObject mit
this.funktion = function() { .... }
als öffentlich vereinbart sind.
Variablen, die mit var definiert wurden, sind privat - sie können nur von Funktionen zugegriffen werden, die innerhalb von MyObject definiert sind; man spricht in diesem Fall von Memberfunktionen.
Erst wenn keine weiteren Referenzen auf MyObject mehr vorhanden sind und a ungültig wurde - z.B. durch:
delete a;
wird das Objekt endgültig zerstört und der Speicher vom Garbage-Collector recycelt.
Variablen, die mit var definiert wurden, sind privat - sie können nur von Funktionen zugegriffen werden, die innerhalb von MyObject definiert sind; man spricht in diesem Fall von Memberfunktionen.
Also schön. Aber müsste ich dann auf diese var nicht auch von anderen Memberfunktionen des Objektes zugreifen können?
mfg
Danny
Variablen, die mit var definiert wurden, sind privat - sie können nur von Funktionen zugegriffen werden, die innerhalb von MyObject definiert sind; man spricht in diesem Fall von Memberfunktionen.
Also schön. Aber müsste ich dann auf diese var nicht auch von anderen Memberfunktionen des Objektes zugreifen können?
Nur mit den sogenannten privilegierten Funktionen, dass sind, die die du in der Konstruktor Funktion anlegst.
function myObj()
{
// Das ist eine private/lokale Variabeln,
// die nur innerhalb der Funktion gültig ist
// aber solange gültig ist, wie das Objekt besteht
var x = 0;
// Ein private Funktion
var quadrat = function()
{
return x * x;
}
// Das eine priviligierte Funktion, die auf alle
// privaten Eigenschaften und Methoden zugreifen kann
this.func = function()
{
return 'Das Quadrat von ' + x + ' = ' + quadrat();
}
}
Damit kannst du in JS echte private Variabeln und Methoden erzeugen, auf die man von aussen nicht zugreifen kann.
x ist ein Bestandteil des Objekte, das du mit der Funktion erzeugst, es ist also nicht wie in einer normalen Funktion, die du aufrufst und nach dem Aufruf ist die Variabel nicht mehr vorhanden.
Struppi.
Damit kannst du in JS echte private Variabeln und Methoden erzeugen, auf die man von aussen nicht zugreifen kann.
x ist ein Bestandteil des Objekte, das du mit der Funktion erzeugst, es ist also nicht wie in einer normalen Funktion, die du aufrufst und nach dem Aufruf ist die Variabel nicht mehr vorhanden.
Struppi.
Das wird jetzt so langsam klarer für mich.
geht es auch mit anderen Memberfunktionen, dass ich private Variablen in nested functions ansprechen kann?
mfg
Danny
Damit kannst du in JS echte private Variabeln und Methoden erzeugen, auf die man von aussen nicht zugreifen kann.
x ist ein Bestandteil des Objekte, das du mit der Funktion erzeugst, es ist also nicht wie in einer normalen Funktion, die du aufrufst und nach dem Aufruf ist die Variabel nicht mehr vorhanden.
Struppi.
Das wird jetzt so langsam klarer für mich.
geht es auch mit anderen Memberfunktionen, dass ich private Variablen in nested functions ansprechen kann?
Was sind nested functions?
In dem Falle sind es private Funktionen, diese können nur von priveligierten Funktionen aufgerufen werden und nur diese beiden können auf private Variabeln zugreifen. Deklarierst du die Funktion mit prototype dann nicht.
Struppi.
Was sind nested functions?
Im Prinzip die Funktionen die man innerhalb einer Funktion deklariert. Der Begriff tauchte in irgend einem Tutorial mal auf.
mfg
Danny
hi,
Nur mit den sogenannten privilegierten Funktionen, dass sind, die die du in der Konstruktor Funktion anlegst.
http://phrogz.net/JS/Classes/OOPinJS.html unterscheidet hier noch zwischen einer "private function" und einer "privileged method" - beide können auf die private Variable zugreifen; wobei die private Funktion nur aus der Objektinstanz selber (von priviligierten Methoden oder dem Konstruktor), die privilegierte Methode aber auch von außerhalb aufgerufen werden kann.
gruß,
wahsaga
Nur mit den sogenannten privilegierten Funktionen, dass sind, die die du in der Konstruktor Funktion anlegst.
http://phrogz.net/JS/Classes/OOPinJS.html unterscheidet hier noch zwischen einer "private function" und einer "privileged method" - beide können auf die private Variable zugreifen; wobei die private Funktion nur aus der Objektinstanz selber (von priviligierten Methoden oder dem Konstruktor), die privilegierte Methode aber auch von außerhalb aufgerufen werden kann.
Genau das schrub ich auch, ausser in dem von dir zitierten Satz, da habe ich die privaten Methoden vergessen, aber in dem Beispiel war sie vorhanden.
Struppi.
hi,
Genau das schrub ich auch, ausser in dem von dir zitierten Satz, da habe ich die privaten Methoden vergessen, aber in dem Beispiel war sie vorhanden.
Öhm ... stimmt :-)
gruß,
wahsaga
Hallo wahsaga.
Wieder eine nützliche Site, danke.
Einen schönen Montag noch.
Gruß, Ashura
hi,
Ich möchte einfach nur durchblicken, wie das funktioniert, sonst nichts.
Mathias hat dir doch eine Seite verlinkt, die es recht ausführlich erklärt.
Wenn du mit dem Verständnis des dort geschilderten Probleme hast, kannst du gerne konkret nachfragen - dabei wäre es sicher hilfreich, wenn du dann auch sagst, womit genau es Probleme gibt.
gruß,
wahsaga
Hallo,
Ich deklariere lokaleVar, diese ist nirgendwo anders als innerhalb des Codeblocks von MeinConstructor () zugänglich. Und doch kann ich sie noch später in einer nested function bei x.func(); erreichen. Was denkt sich denn der Interpreter dabei? Woher weiß er, dass lokaleVar noch beibehalten werden soll? Mich interessiert doch nur, wie das intern funzt.
Ich würde die Privilegien einer »priviligierten« Methode so erklären:
Die Konstruktorfunktion hat einen eigenen Scope mit lokalen Variablen, pipapo. Wenn man nun in der Konstruktorfunktion eine andere Funktion notiert, wirkt diese als Closure und schließt in ihrem Scope hat man somit Zugriff auf alle lokalen Variablen des Scopes der Konstruktorfunktion.
Das ist also keine Eigenheit von Konstruktorfunktionen und darin über this im gegenwärtigen Objekt gespeicherten sog. priviligierten Methoden, sondern funktioniert bei allen anderen Funktionen auch. Eine Konstruktorfunktion ist auch nichts anderes als eine Funktion, in der »this« auf das kreierte Objekt zeigt.
*Wo* also die Funktion, die im Konstruktor notiert wird, gespeichert wird, ist nicht relevant. Man kann sie im this-Objekt speichern, aber auch irgendwo anders. Sie wirkt trotzdem als Closure und schließt den Konstruktor-Scope ein:
function f1 () {
var lokal = "bla";
window.f2 = function () { alert(lokal); }
}
var instanz = new f1;
f2();
Das geht wie gesagt auch ganz ohne new:
function f1 () {
var lokal = "bla";
window.f2 = function () { alert(lokal); }
}
f1();
f2();
Priviligierte Methoden sind also nichts anderes als im Konstruktor definierte Closures.
Nicht-priviligierte Methoden sind all jene, die außerhalb des Konstruktors definiert wurden und demnach keinen Zugriff auf dessen Scope haben.
Insofern unterscheidet JavaScript nicht extra zwischen priviligierten und nicht-priviligierten Methoden, sondern es handelt sich einfach um das allgemeine Feature der Closures.
Mathias
Dieses Beispiel erzeugt eine interessante Objektverzeigerungsstruktur:
function f1 () {
var lokal = "bla";
window.f2 = function () { alert(lokal); }
}
f1();
f2();
Nachdem f1() terminiert hat, gibt keine direkte Referenz auf das dabei erzeugte Objekt.
Der Aufruf von f1() erzeugt ein lokales Function-Objekt im Scope von f1 - eine Referenz darauf wird an window.f2 zugewiesen - und die private Variable lokal.
Es existieren zwei Referenzen auf das Function-Objekt: Eine vom Scope von f1 und eine von window.f2
Das Funktionsobjekt enthält eine Referenz auf die f1-Instanz.
Damit existiert eine indirekte Referenz von window.f2 auf die f1-Instanz, die damit gültig bleibt, bis an window.f2 ein anderer Wert zugewiesen oder (die Varible!) window.f2 mit delete entsorgt wird - vorausgesetzt, es wurden zwischenzeitlich keine weiteren Referenzen erzeugt.
Die internen Abläufe in dieser Situation sind in den Details recht verwickelt, denn es muß geprüft werden, ob noch irgendwelche Referenzen auf ein Objekt vorhanden sind und wenn ja, ob es Zirkularreferenzen sind, die keinen externen Zugriff auf das Objekt mehr ermöglichen. Gerade im obigen Beispiel wird das ziemlich schwierig. (Wenn der Garbage-Collector dabei patzt, entsteht ein Speicherleck - der IE hatte zumindest mal derartige Probleme.)
Zum new-Operator: Er ist im Vergleich zu seinem Namensvetter in C++ geradezu ein Mickerling.
Er allokiert keinen Speicher, sondern gibt im Beispiel
var a = new f1();
nur eine Referenz auf die Instanz von f1 zurück, die beim Aufruf entstanden ist, die Instanz überlebt dadurch das Terminieren der Konstruktorfunktion.