Name von Objekten
Jürgen Berkemeier
- javascript
Hallo,
gibt es in Javascript eine Möglichkeit, den Namen von Objekten zu ermitteln, unter dem sie angelegt wurden?
Ich habe ein eigenes Objekt:
function test(par) {
...
this.alrt=function() {
alert(this.???); // hier fehlt mir die Eigenschaft/Methode
}
}
var Test1=new test("abc");
var Test2=new test("efg");
Test1.alrt(); // soll "Test1" melden
Test2.alrt(); // soll "Test2" melden
Gruß, Jürgen
Hallo Jürgen,
Test1 und Test2 verweisen nur auf ein bestimmtes Objekt, das kann sich aber jeder Zeit ändern, außerdem können sehr viele Referenzen auf das selbe Objekt zeigen.
Wenn ein Objekt irgendwo wissen muss, von wo aus es referenziert wird, solltest Du Dir einfach etwas besseres überlegen. Die Lösung wäre vermutlich sowieso nicht so sehr geschickt geworden.
Grüße
Daniel
gruss Daniel,
...
...
danke Deiner aufmerksamkeit - Dein posting
hat mich erst auf Jürgens wahres problem
gestossen;
so long - peterS. - pseliger@gmx.net
gruss Jürgen,
gibt es in Javascript eine Möglichkeit, den Namen von Objekten
zu ermitteln, unter dem sie angelegt wurden?
du suchst die "constructor"-eigenschaft eines objekts;
"myObj.constructor" haelt die reference auf die konstruktor-
funktion, mit welcher "myObj" generiert wurde;
Dein bsp. etwas abgewandelt.:
//der namenskonvention folgend sollte der konstruktor
//immer mit einen grossen anfangsbuchstaben haben;
function TestObject(par) {
this.param = par;
}
//die namenskonvention konsequent weiterverfogend sollte
//man alle objekte, die nicht konstruktor und nicht konstante
//sind, mit einem kleinen buchstaben beginnen lassen;
var testObj01 = new TestObject("abc");
var testObj02 = new TestObject("xyz");
alert("testObj01.param = " + testObj01.param);
alert("testObj02.param = " + testObj02.param);
alert("testObj01.constructor= " + testObj01.constructor);
alert("testObj02.constructor= " + testObj02.constructor);
Dein wunsch
Test1.alrt(); // soll "Test1" melden
Test2.alrt(); // soll "Test2" melden
laesst sich mit einer prototypen-methode fuer
alle objekte erschlagen, die sich auf das
globale objekt "Object" zurueckfuehren lassen:
Object.prototype.getConstructorName = function() {
//etwas code;
};
diese methode findest Du auf:
http://www.pseliger.de/jsExtendedApi/jsApi.Object.typeDetection.dev.js bzw.
http://www.pseliger.de/jsExtendedApi/jsApi.Object.typeDetection.js
weiter unten im forum kann man noch folgendes lesen:
[pref:t=76858&m=443178]
viel erfolg - peterS. - pseliger@gmx.net
hallo again Jürgen,
da hab' ich wieder mal zu schnell geschossen - nach
gibt es in Javascript eine Möglichkeit, den Namen von
Objekten zu ermitteln, unter dem sie angelegt wurden?
habe ich mich im zweiten teil
Test1.alrt(); // soll "Test1" melden
Test2.alrt(); // soll "Test2" melden
glatt verlesen - tut mir leid;
aber wofuer musst Du denn den variablen-namen des objekts
wissen?
fragend - peterS. - pseliger@gmx.net
Hallo Peter,
vielen Dank für deine Hilfe.
da hab' ich wieder mal zu schnell geschossen - nach
gibt es in Javascript eine Möglichkeit, den Namen von
Objekten zu ermitteln, unter dem sie angelegt wurden?
habe ich mich im zweiten teil
Test1.alrt(); // soll "Test1" melden
Test2.alrt(); // soll "Test2" melden
glatt verlesen - tut mir leid;
hab ich inzwischen auch gemerkt. Aber dafür kenne ich jetzt ".constructor".
aber wofuer musst Du denn den variablen-namen des objekts
wissen?
Ich lege ein Objekt mit einigen Methoden an. Dieses Objekt wird im HTML über javascript:... oder onclick=... aufgerufen. Für Besucher, die ohne JS unterwegs sind, soll der Link aber nicht erscheinen. Also soll das Objekt selbst, wenn es angelegt wird, den Link auf seine Methode anlegen. Bisher mache ich das über eine extra Funktion.
Gruß, Jürgen
gruss Jürgen,
Ich lege ein Objekt mit einigen Methoden an. ... Also soll
das Objekt selbst, wenn es angelegt wird, den Link auf seine
Methode anlegen. Bisher mache ich das über eine extra Funktion.
schoen - kannst Du das jetzt noch mal konkreter, vielleicht
auch an einem bsp, welches auf Dein eigentliches problem
eingedampft ist, erklaeren? - das waere ganz nett, da ich in
meinem nachmittagstief nicht mehr so gut abstrahiere ;-)
bis bald - peterS.- pseliger@gmx.net
Hallo Peter,
ich habe einen Tabellensortierer: http://home.vrweb.de/j.berkemeier/TableSort.html.
Die Links zum Sortieren in der Überschrift sind nur da, wenn der Besucher Javascript eingeschaltet hat und sein Browser DOM-fähig ist. Daher kann ich sie nicht einfach ins HTML schreiben. Im Moment werden die Überschriften durch eine extra Funktion gesetzt. Ich möchte aber diese Funktion in das Sortierobjekt integrieren.
Gruß, Jürgen
gruss Jürgen,
ich habe einen Tabellensortierer: http://home.vrweb.de/j.berkemeier/TableSort.html.
//ok - was spricht denn dagegen, fuer jedes "JB_Table"
//-objekt ueber seinen konstruktor die dort schon
//existierende variable "Tab" ueber "this.Tab" als
//referenz auf das jeweilige [HTMLTableElement]
//festzunageln;
//
//das saehe dann in etwa so aus:
function JB_Table(tabId,vorsort) {
var ssort = vorsort ;
var arr = new Array();
this.tab = document.getElementById(tabId);
//jetzt mit "this.tab" weiterarbeiten - oder:
//this.node = document.getElementsByTagName("table")[tabId];
//wobei der konstruktor "this.node" schon
//auf dessen existenz pruefen sollte;
//...Dein code;
}
//jetzt kann die globale funktion "Text2Link" auch als
//prototypen-methode fuer das objekt "JB_Table" umgesetzt
//werden:
JB_Table.prototype.text2Link = function() {
tableNode = this.node; // zur veranschaulichung;
//jetzt hat man vollen zugriff auf die
//zu jedem "JB_Table"-objekt zugehoerige
//tabelle;
//...Dein code;
};
//die globale funktion "start" kann jetzt ebenfalls
//wie gewuenscht gekuerzt werden;
function start() {
if (document.getElementsByTagName('body')[0].replaceChild) {
var i;
document.getElementById("Hinweis").firstChild.nodeValue="Ein Klick auf die Spaltenüberschrift sortiert die Liste" ;
Tabelle1 = new JB_Table("Tab1",0);
Tabelle1.text2Link();
//das gehoert dann in abgewandelter form in die prototypen methode "text2Link";
//for (i=0; i<5; i++) {
// Text2Link("Kopf0_"+i,"javascript:Tabelle1.sort("+i+")");
//}
Tabelle2 = new JB_Table("Tab2",1);
Tabelle2.text2Link();
//... siehe gerade eben ...;
}
by(t)e by(t)e - peterS. - pseliger@gmx.net
Hallo,
in JB_Table kann ich natürlich auf alle Tabellenelemente zugreifen. Das ist ja auch nicht das Problem. Ich muss, um den Link auf die sort-Methode zu setzen, wissen, wie das Objekt heißt. Mein momentaner Ansatz sieht so aus:
function JB_Table(TabId,vorsort,sortlinks,varName) {
// ^
// nicht schön. Besser wäre varName=this.???;
...
var linknr=sortlinks.split(",");
...
var titel=document.getElementById(TabId).getElementsByTagName("thead")[0].
getElementsByTagName("tr")[0].getElementsByTagName("th");
for(var l=0;l<linknr.length;l++) {
var lnr=parseInt(linknr[l])-1;
var Ziel="javascript:"+varName+".sort("+lnr+")";
if (lnr>=0 && lnr < nspalten) Text2Link(titel[lnr],Ziel);
}
...
und
Tabelle1=new JB_Table("Tab1","1","1,2,3,4,5","Tabelle1");
Tabelle2=new JB_Table("Tab2","2","1,2,3,4","Tabelle2");
d.h. ich sage dem Objekt, wie es heißt. Ich möchte aber, dass das Objekt seinen Variablennamen selbst ermittelt.
Gruß, Jürgen
gruss Jürgen,
... Ich muss, um den Link auf die sort-Methode zu setzen,
wissen, wie das Objekt heißt. Mein momentaner Ansatz sieht
so aus:
...
mhh ... ein ansatzt, wenn auch ein dreckiger, eigentlich
nicht zu empfehlender - und Daniel hat schon alles ueber
das warum gesagt - waere dieser:
a) Du hast eine voll kontrollierbare statische umgebung,
in dem sinne, dass es eine endliche anzahl von html-
tabellen mit einem einheitlichen namens-schema ueber
deren id-attribute gibt;
b) eine initialisierungsfunktion fischt sich alle table-
knoten aus dem DOM und prueft deren ids auf diese
namenskonvention;
c) fuer jede zum schema passende html-tabelle wird ein
globales js-objekt erzeugt - nach dem jetzigen schema
koennte das dann so aussehen:
var tableCollection = document.getElementsByTagName("table");
if (tableCollection) {
var i, node, varName, objCounter = 0;
for (i=0; i<tableCollection.length; i++) {
node = tableCollection[i]
if (node.id && (node.id != "")/*&& weiter bedingungen*/) {
varName = "tabelle" + objCounter;
window[varName] = new JB_Table(node, .., varName);
//hier werden globale variablen
//mit dem namen "varName" erzeugt;
objCounter ++;
}
}
}
der konstruktor erhaelt dann statt der node-id gleich die
dom-referenz auf den html-table und "varName" wird als
name des gerade global zu erzeugenden "JB_Table"-objekts
dem konstruktor zur weiterverwendung mitgegeben:
this.windowName = varName;
d) wenn jetzt link-text generiert werden soll, kann auf
"this.windowName" zugegriffen werden - ungefaehr so:
linkText = "javascript:" + this.windowName + ".sort()";
was fuer z.b. "var Tabelle2 = new JB_Table(.., .., ..);"
und einer methode "sort" fuer jedes "JB_Table"-objekt
diesem hier entspraeche: "Tabelle2.sort();"
e) nocheinmal: sobald eine umgebung nicht in diesem masse
gewaehrleistet werden kann, muss man sich Daniels argu-
mentation beugen;
by(t)e by(t)e - peterS. - pseliger@gmx.net
Hallo!
Es geht also darum Tabellen zu sortieren. Dabei soll die Kompfzeile nur erzeugt werden, wenn die Tabelle sortiert werden soll.
Ich würde das so lösen:
var tables = new Array();
//Ein Objekt für die sortierbaren Tabellen
function SortableTable(compare, head, table) {
this.compare = compare; //Eine Funktion, die zwei Zeilen vergleicht und -1, 0, 1 für kleiner/gleich/größer zurück gibt.
this.header = header; //Eine Funktion, die den Header ausgibt
this.table = table //Die zu sortierende Tabelle
this.sortTable = sortTable;
this.table.insertChildNode(this.header(), 0);
tables[id] = this;
}
function sortTable(spaltenNummer) {
var elems = this.table.getElementsByTagName("tr");
//Sortieren der Zeilen mit irgend einem Sortieralgorithmus unter verwendung von compare(elem1, elem2);
for(var a = 0; a < elems.length; a++) {
this.table.removeChildNode(elems[a]);
this.table.appendChildNode(elems[a]);
}
}
Header kann dann Eventhandler so nach folgendem Schema erzeugen:
var handler = "onclick='tables[" + this.id + "]'.sortTable(" + nr + ")";
Dann kann man mit onload="" eine Initialisierungsfunktion aufrufen, die nur noch folgendes tun muss:
new Table(myCompare, myHeader, document.getElementById("tableId"));
Die DOM-Methoden stimmen vermutlich nicht alle, aber darauf kommt es ja auch nicht so an ;-)
Grüße
Daniel
Hallo,
danke Euch beiden. Aber der Tabellensortierer ist schon fertig. Die Routine, die einen Text in einen Link umwandelt, auch. Das Einzige, was ich benötige, ist, wie ich innerhalb eines Objektes an den Variablennamen dieses Objektes komme.
Also wie im Eröffnungsposting;
function test() {
alert(this.?Variablenname?);
}
und
ABC=new test() soll ABC mit dem alert ausgeben,
DEF=new test() soll DEF mit dem alert ausgeben.
aber offensichtlich geht so etwas nicht.
Daher die "schlechte" Lösung:
function test(name) {
alert(name);
}
und
ABC=new test("ABC");
Gruß, Jürgen
Hallo Jürgen,
danke Euch beiden. Aber der Tabellensortierer ist schon fertig. Die Routine, die einen Text in einen Link umwandelt, auch. Das Einzige, was ich benötige, ist, wie ich innerhalb eines Objektes an den Variablennamen dieses Objektes komme.
Ja aber diese gibt es (aus guten Gründen) nicht.
Wenn Dein Konzept darauf aufbaut, ist es eben hinfällig.
Daher haben wir ja andere Möglichkeiten vorgeschlagen
Daher die "schlechte" Lösung:
Nun, wenn Du mit einer Lösung zu frieden bist, die Du selbst als schlecht einstufst, ist das natürlich auch ok ;-)
Grüße
Daniel
gruss Jürgen,
Also wie im Eröffnungsposting;
...
...
aber offensichtlich geht so etwas nicht.
Daher die "schlechte" Lösung:
function test(name) {
alert(name);
}
und
ABC=new test("ABC");
naja, selbst wenn diese loesung "schlecht" sein sollte, so
ist sie doch legitim - das hab' ich doch weiter oben schon
so ge- und beschrieben;
es gibt aber dennoch eine moeglichkeit, das "referenzloch"
zwischen einem js-objekt und dem zugriff auf dieses objekt
oder auf eine seiner eigenschaften bzw. dem aufruf einer
seiner methoden aus einer dynamisch geschriebenen client-
oberflaeche heraus elegant zu ueberbruecken;
das wird jetzt etwas laenger - vorueberlegungen:
a) kann man fuer den einsatz seiner selbstgeschriebenen
konstruktor-funktionen immer sicherstellen, das diesem
der name der zu initilisierenden objekt-variable ueber-
geben wird? - nicht zweifelsfrei;
dieser, die ganze zeit als "dreckig" diskutierte ansatz,
faellt also aus, obwohl es schon sehr nahe liegt, namen
von globalen variablen ueber deren uebergeordnetes objekt
"window" zu benutzen - bsp.:
die globale definition einer variablen "testObject" kann
in einem js-client hoechst unterschiedlich ausfallen -
var testObject = new Object(); testObject.status = "test";
//oder aber
window.testObject = {status:"test"}; // aber auch
window["testObject"] = {status:"test"};
in der letzten zeile steckt dann der schluessel fuer die
referenzierung auf ein objekt, dessen variablen-namen
bekannt ist (z.b. einer konstruktor-funktion, die diesen
string-wert einem objekt mit auf dem weg gibt);
zur referenzierung dient dann ein string, der auch in die
oberflaeche des html-clients geschrieben werden kann:
"alert(window['" + variablenName + "'].status);"
b) wie kann man den ansatz aus a) - zuhilfenahme einer
"string-referenz" - retten, obwohl a) verworfen
werden muss?
es gibt zwei globale objekte im js-faehigen html-client:
"window" als oberste "instanz" fuer alle "HTMLElement"-
objekte und "Object" als oberste "instanz" fuer alle
js-objekte;
wenn kein string-wert (KEY) fuer den namen einer objekt-
variablen verwendet werden darf, wie sieht es dann mit
einer anderen form der "speicherung" aus - z.b.: INDEX?
das ist es - loesung:
(zum besseren verstaendnis werden nur die fundamentalen
bestandteile vorgestellt, das ergebnis ist dann zwar
funktionstuechtig aber in seiner gesamtheit angreifbar)
c) man erweitert das oberste js-objekt "Object" um ein array,
dessen eintraege referenzen auf js-objekte jeglicher art
sein sollen:
Object.selfReferences = [];
desweiteren benoetigt jedes js-objekt eine setter- bzw.
getter-methode fuer seine referenz - beide methoden
werden als prototypen ueber "Object" implementiert;
bei benutzung des setters "setSelfReference" wird dem
array "Object.selfReferences" die referenz des aufruf-
enden objekts hinzugefuegt - gleichzeitig bekommt das
aufrufende objekt die eigenschaft "selfIndex" zugewiesen,
deren numerischer wert dem index der objektreferenz im
genannten array entspricht:
Object.prototype.setSelfReference = function() {
this.selfIndex = Object.selfReferences.length;
Object.selfReferences[this.selfIndex] = this;
};
vor der umsetzung des getters soll noch einmal an den
zweiten teil von a) mit dem fiktiven ergebnis -
"alert(window['" + variablenName + "'].status);" -
erinnert werden - etwas in der art, bezogen auf
"Object.selfReferences", soll dabei schon herauskommen;
der rueckgabewert soll ein string sein, der in seiner
evaluierten form, den zugriff auf das die getter-methode
aufrufende objekt zulaesst - also so:
"Object.selfReferences[0]"
Object.prototype.getSelfReference = function() {
return ("Object.selfReferences[" + this.selfIndex + "]");
};
der einsatz eines an "Object" gebundenen arrays und die
verfuegbarkeit von setter- und getter-Object-prototypen
ermoeglicht es jedem js-objekt(auch teil-objekten eines
js-objektes) referenzen auf denkbar einfache weise und
unabhangig von den namen moeglicher objektvariablen zu
schreiben und zu lesen;
einem einsatz steht jetzt nichts mehr im wege - nur -
der bis hierher vorgestellte loesung fehlt es an einer
methode, selbstreferenzen sauber zu loeschen, oder aber
das array von "unsauber" auf null gesetzten referenzen
zu befreien;
die runde komplettloesung implementiert deshalb folgende
eigenschaften:
das array : Object.selfReferences;
die methode : Object.selfReferences.isFragmented;
die methode : Object.selfReferences.defragment;
die methode : [obj].setSelfReference;
die methode : [obj].getSelfReference;
die methode : [obj].removeSelfReference;
nachzuschauem unter:
http://www.pseliger.de/jsExtendedApi/jsApi.Object.selfReferences.dev.js
anzuwenden mit:
http://www.pseliger.de/jsExtendedApi/jsApi.Object.selfReferences.js
doch nun zuruck zum konstruktor "JB_Table":
die methoden "VglFkt" und "sort" lassen sich auch als
prototypen-methoden von "JB_Table" umsetzen, wenn einige
lokale variablen des konstruktors wie z.b. "ssort" jedem
"JB_Table"-objekt als eigenschaften mitgegeben werden (this);
function JB_Table(tabId,vorsort) {
this.setSelfReference();
this.tabId = tabId;
//Dein code;
}
JB_Table.prototype.vglFkt = function(a,b) {
//Dein code
};
JB_Table.prototype.sort = function(s) {
//Dein code
};
die globale funktion "Text2Link" kann jetzt auch als
prototypen-methode fuer das objekt "JB_Table" umgesetzt
werden:
JB_Table.prototype.text2Link = function() {
//moeglicherweise:
var action = "javascript:" + this.getSelfReference() + ".sort(";
//for(var i=0;i<5;i++) Text2Link("Kopf0_"+i,"javascript:Tabelle1.sort("+i+")") ;
//die zeile hier darueber muss dahingehend abgewandelt
//werden, dass ueber "this.tabId" auf den "tr"-knoten
//zugegriffen wird, welcher die zu aendernden "td"-
//knoten enthaelt; die knoten werden einzeln durch
//gezaehlt und angepasst - vielleicht so: action + i + ")"
//Dein code;
};
viel erfolg - gute nacht - peterS. - pseliger@gmx.net
Hallo Peter,
das ist ja eine sehr ausführliche Antwort. Leider habe ich beim ersten Lesen nicht alles verstanden. Aber für mich sieht es so aus, dass ich ca. 100 Zeilen Javascript benötige, um an den Variablennamen zu kommen. Da bleibe ich doch lieber bei der "uneleganten" Methode und teile dem Objekt einfach seinen Namen als Übergabeparameter mit. Trotzdem Dir und Daniel vielen Dank.
Gruß, Jürgen
gruss Jürgen,
... Leider habe ich beim ersten Lesen nicht alles verstanden.
schade, ich haette gedacht so eine art initialzuendung zu
liefern - vielleicht reicht es ja fuer ein spaeteres und
dafuer umso intensiveres AHA-erlebnis ;-)
... Aber für mich sieht es so aus, dass ich ca. 100 Zeilen
Javascript benötige, um an den Variablennamen zu kommen.
??? wie jetzt, Du koenntest Deinen gesamtcode sogar entscheidend
verkuerzen - ausserdem waere das ergebnis uebersichtlicher;
Da bleibe ich doch lieber bei der "uneleganten" Methode und teile
dem Objekt einfach seinen Namen als Übergabeparameter mit.
jo - wie schon mehrfach gesagt, bei einer ueberschaubaren
umgebung mit wenigen tabellen ist dieser ansatz ueberhaupt
nicht verwerflich;
so long - peterS. - pseliger@gmx.net
Hallo,
oder eine Kurzfassung:
Im Moment:
var test1=new Test();
makelink("test1"); //setzt Link javascript:test1.tuwas()
var test2=new Test();
makelink("test2"); //setzt Link javascript:test2.tuwas()
...
"schlechte" Idee:
var test1=new Test("test1"); // makelink wird in Test aufgerufen
var test1=new Test("test1"); // und Test bekommt Variablennamen übergeben
...
Ziel:
var test1=new Test(); // makelink wird in Test aufgerufen
var test2=new Test(); // und Test kennt seinen Variablennamen.
Aber wie kommt Test an seinen Variablennamen heran? Oder geht sowas nicht?
Gruß, Jürgen
gruss Jürgen,
Hallo,
oder eine Kurzfassung:
zu spaet ;-)
Aber wie kommt Test an seinen Variablennamen heran? Oder geht sowas nicht?
muss er bei dieser problemstellung gar nicht:
jedes objekt bekommt bei seiner initialisierung
den ihm entsprechenden tabellenknoten rangetackert -
das war's schon - ausfuehrlicher wird es weiter
unten im thread;
tschoe - peterS. - pseliger@gmx.net