Ergebnis 1 bis 10 von 10
  1. #1
    Jodli ist offline Jungspund
    registriert
    24-06-2006
    Beiträge
    21

    bestehendes Object einer Klasse "zuweisen"

    Hallo Leute.
    Ich bin schon set längerem am rumprobieren und bin nun zu dem Punkt gekommen, an dem mir die Ideen ausgegangen sind und ich nach Rat suche.
    Ich hoffe man kann mir helfen


    Ich bastle immer wieder an Scripts, bei denen es oft vorkommt, dass ich neue child-Nodes irgendwo einfügen muss.
    Um diesen Vorgang ein wenig abzukürzen, dachte ich mir, ich schreibe mir ne nette Funktion, welcher ich nur die Attribute übergeben muss, und die mir das Object dann an den gewünschten Ort einfügt.

    Nach mehreren Versuchen war mein bester Versuch bisher diese Funktion:

    Code:
    function appendElement(e_child, e_parent, attr, e_style) {
    	var e = document.createElement(e_child);
    	for(var i in attr)
    		e[i] = attr[i];
    	for(var i in e_style)
    		e.style[i] = e_style[i];
    	e_parent.appendChild(e);
    	return e;
    }
    Eigentlich relativ simpel. Die Attribute werden einem Object übergeben, welches dann durchgegangen wird und dann auf ein frisch erstelltes Element übertragen werden.

    Die Tatsache, dass css-Deklarationen getrennt übergeben werden müssen, stört mich nicht sonderlich.
    Der große Nachteil liegt für mich in der Tatsache, dass zuerst ein Object erstellt werden muss, dieses dann mit einer Schleife durchgegangen wird und dann in ein neues Object (das Node-Object) übertragen werden müssen.
    Also drei Vorgänge, anstatt nur einem.

    Mein nächster Gedanke war dann, dass es sich ja bei Nodes ebenfalls um Objekte handelt. Ich müsste also das übergebene Object also lediglich der HTMLDivElement-Klasse (beispielsweise) "zuweisen" oder den Node-Konstruktor "nachbauen", dann müsste es doch auch klappen.
    Daran scheitere ich leider bisher...

    Hat vielleicht jemand eine Idee, wie man diesen Ansatz umsetzen könnte bzw, was es noch für Wege gäbe, die Schleifen zu umgehen?
    Wäre toll, wenn jemand was zündendes (oder abgebranntes) beisteuern kann

    Frohe Ostern
    Jodli
    Geändert von Jodli (24-04-2011 um 20:22 Uhr)

  2. #2
    Avatar von kkapsner
    kkapsner ist offline Super Moderator
    registriert
    28-03-2008
    Beiträge
    17.757

    AW: bestehendes Object einer Klasse "zuweisen"

    Das was du da machen willst ist meines Wissens nach nicht möglich und wenn, ist es viel komplizierter als diese einfache Schleife.

  3. #3
    Jodli ist offline Jungspund
    registriert
    24-06-2006
    Beiträge
    21

    AW: bestehendes Object einer Klasse "zuweisen"

    Hm danke für die Antwort.
    Und siehst du einen anderen Weg, wie ich das Erstellen von Nodes in eine Funktion packen kann, ohne den Zusatz-Aufwand für den Browser in die Höhe schießen zu lassen?

  4. #4
    Avatar von kkapsner
    kkapsner ist offline Super Moderator
    registriert
    28-03-2008
    Beiträge
    17.757

    AW: bestehendes Object einer Klasse "zuweisen"

    So groß ist der Zusatzaufwand bei deiner Methode auch nicht...

  5. #5
    Jodli ist offline Jungspund
    registriert
    24-06-2006
    Beiträge
    21

    AW: bestehendes Object einer Klasse "zuweisen"

    Naja, dreimal höher, als wenn ich das Element ohne Funktion einfügen würde.

    Und da sind die zusätzlichen Operationen am Stack, welche durch den Aufruf der Funktion notwendig werden, sowie die zusätzlich induziert Object-Variablen, noch gar nicht einberechnet.

    Du hast schon recht, wenn ich hin und wieder Elemente einfüge, dürfte das ziemlich wurscht sein.

    Aber wenn ich eine Schleife habe, welche ein paar 100 Elemente durchgeht und jeweils ein paar Childs mit vielen Attributen einfügt, dürfte das schon einen Unterschied machen.
    Und das kann bei meinem momentanen Script-Projekt leider durchaus vorkommen.
    Verstärkend kommt noch hinzu, dass in meinem Fall in eine Seite eingefügt wird, welche die Javascript-Engine sowieso schon bis zum Maximum ausreizt.

  6. #6
    ein schlauer ist offline Lounge-Member
    registriert
    18-08-2004
    Beiträge
    14.671

    AW: bestehendes Object einer Klasse "zuweisen"

    Zitat Zitat von Jodli Beitrag anzeigen
    Naja, dreimal höher, als wenn ich das Element ohne Funktion einfügen würde.
    Ich weiß nicht, wo du den Mehraufwand siehst. Ob du Eigenschaften im Konstruktor eines Objektes übergibst oder in einer Funktion spielt keine Rolle. Und solche Sachen wie der Stack spielen vielleicht intern eine Rolle, aber du bist hier nicht auf Maschinenebene. Auch Objekte erzeugen, ist kein zeitrelevantes Problem. Der größte Flaschenhals bei JS Anwendungen sind DOM Methoden oder -manipulationen, dafür gibt es aber Optimierungen. Ein interessanter Vortrag zum Thema: YouTube - Speed Up Your JavaScript

  7. #7
    Jodli ist offline Jungspund
    registriert
    24-06-2006
    Beiträge
    21

    AW: bestehendes Object einer Klasse "zuweisen"

    Also soweit ich das sehe, ist der Unterschied zwischen einem Object und einem Node-Object (welches noch nicht in den DOM eingefügt wurde!) nicht sonderlich groß, außer dass ein Node-Object ein paar Eigenschaften mehr hat.
    Wenn ich den Gedankengang also weiterspinne, erstelle ich im Normalfall ein Object und weise diesem die Eigenschaften zu (um dieses dann per appendChild) in die Seite zu übertragen.
    Spiele ich das ganze über meine Funktion, wird zuerst ein Object erzeugt, dieses an eine Funktion übergeben, welches dieses per Schleife nochmal durchgeht und ein Node-Object erzeugt.
    Erst dann wird das Object an appendChild übergeben.

    Daher meine Rede von Mehraufwand.

    Aber wenn ihr meint, dass die Relationen da zu gering sind, will ich euch das glauben. Über die Aufwandsunterschiede weiß ich relativ schlecht bescheid
    Hierbei handelt es sich nur um meine meistgenutzte Funktion (da ich leider sehr oft DOM-Manipulationen benötige - Greasemonkey undso), weswegen da ein wenig Optimierung sehr praktisch gewesen wäre^^

    Ich danke für eure Hilfe.
    Und danke für den Link. Werd ich mir bei Gelegenheit reinziehen.
    Geändert von Jodli (25-04-2011 um 16:13 Uhr) Grund: Fehlersuche

  8. #8
    Avatar von kkapsner
    kkapsner ist offline Super Moderator
    registriert
    28-03-2008
    Beiträge
    17.757

    AW: bestehendes Object einer Klasse "zuweisen"

    Der Unterschied ist wirklich nicht besonders groß:
    Code:
    <!DOCTYPE html>
    
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Fenstertitel</title>
    </head>
    <body>
    <script type="text/javascript">
    function appendElement(e_child, e_parent, attr, e_style) {
    	var e = document.createElement(e_child);
    	for(var i in attr)
    		e[i] = attr[i];
    	for(var i in e_style)
    		e.style[i] = e_style[i];
    	e_parent.appendChild(e);
    	return e;
    }
    
    var parent = document.body;
    //parent = document.createElement("div");
    var times = 1000, i;
    var t = new Date();
    for (i = 0; i < times; i++){
    	var node = document.createElement("span");
    	node.id = "test" + i;
    	node.innerHTML = " ";
    	node.style.backgroundColor = "black";
    	parent.appendChild(node);
    }
    document.write(new Date() - t + "<br>");
    //parent = document.createElement("div");
    t = new Date();
    for (i = 0; i < times; i++){
    	appendElement("span", parent, {id: "test" + i, innerHTML: " "}, {backgroundColor: "black"});
    }
    document.write(new Date() - t);
    </script>
    </body>
    </html>

  9. #9
    Jodli ist offline Jungspund
    registriert
    24-06-2006
    Beiträge
    21

    AW: bestehendes Object einer Klasse "zuweisen"

    Ich denke nicht, dass dein Beispiel repräsentativ ist.
    Klar ist der Mehraufwand bei wenigen Attributen umso geringer.

    Ich hab versucht ein bissl rumzuspielen und halte mal meine Ergebnisse für die Nachwelt hier fest:

    Vorweg: Zwischen meinem ff und anderen Browsern liegen etwa 20 ms an Ausführungszeit.
    Was daran liegt, dass mein FF mal wieder eine Profilbereinigung nötig hat.
    Aber das kommt mir in diesem Fall auch entgegen, da die Seite, in welche ich eingreifen möchte, den Browser sowieso an seine Grenzen bringt und ja auch Spieler mit langsameren PCs etwas davon haben sollen.
    Meine Funktion benötigt bei 100 Nodes im Schnitt 30 ms. Direktes Einfügen liegt in etwa bei 20 ms.

    Es ist ein relativ großer Unterschied, ob man der appendElement-Funktion die Javascript-, oder die css-Notation übergibt.

    Also:
    Code:
    appendElement(EL, PARENT, ATTR, {marginTop:'5px'})
    ist langsamer als
    Code:
    appendElement(EL, PARENT, ATTR, {'margin-top':'5px'})
    Desweiteren kann man den Code ordentlich (zumindest im ff. Im Chrome ist zwar ebenfalls eine konstante Differenz, aber diese ist nicht in so hoher Relation) beschleunigen , indem man das style-Atribut per cssText und nicht einzeln bearbeitet.

    Mit innerHTML statt erzeugter Nodes zu arbeiten ist auch einen Gedanken Wert. Allerdings kann die Ausführen da auch recht schnell in die Höhe schnellen.
    Und man muss aufpassen, dass EventListener nicht ihre Wirkung verlieren.

    Mein Test-Code:

    Code:
    <!DOCTYPE html>
    
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Fenstertitel</title>
    </head>
    <body onLoad="start()">
    <script type="text/javascript">
    function appendElement(e_child, e_parent, attr, e_style) {
    	var e = document.createElement(e_child);
    	for(var i in attr)
    		e[i] = attr[i];
    	
    	for(var i in e_style)
    		e.style[i] = e_style[i];
    	e_parent.appendChild(e);
    	return e;
    }
    function appendElement2(eT, attr, e_style, eP) {
    	var e = document.createElement(eT);
    	for(var i in attr)
    		e[i] = attr[i];
    	
    	e.style.cssText=e_style;
    	eP.appendChild(e);
    	return e;
    }
    function appendElement3(eT, attr, iH, e_style, eP) {
    	var e = document.createElement('div');
    	e.innerHTML='<'+eT+' '+attr+' style="'+e_style+'">'+iH+'<'+eT+'>';
    	eP.appendChild(e.firstChild);
    	return e.firstChild;
    }
    function appendElement4(html, eP) {
    	var e = document.createElement('div');
    	e.innerHTML=html;
    	eP.appendChild(e.firstChild);
    	return e.firstChild;
    }
    function appendElement5(html, eP) {
    	eP.innerHTML=html
    	return eP.firstChild;
    }
    
    function start() {
    	var parent = document.body, times = 100, i, t, stat= new Object;
    
    	/*******************	0	*******************/
    	t = new Date();
    	for (i = 0; i < times; i++){
    		appendElement('span', parent, {id: 'test' + i, lang:234, innerHTML: ' '}, {backgroundColor: 'black', border:'1px solid black', marginTop:'5px', fontSize:'10px', position:'absolute', left:'125px', top:'50px', width:'10px', height:'10px'});
    	}
    	stat['old_appendFunction']=new Date() - t;
    
    
    	/*******************	1	*******************/
    	t = new Date();
    	for (i = 0; i < times; i++){
    		appendElement('span', parent, {id: 'test' + i, lang:234, innerHTML: ' '}, {'background-color': 'black', border:'1px solid black', 'margin-top':'5px', 'font-size':'10px', position:'absolute', left:'125px', top:'50px', width:'10px', height:'10px'});
    	}
    	stat['old_appendFunction_with_cssNotations']=new Date() - t;
    
    	/*******************	2	*******************/
    	t = new Date();
    	for (i = 0; i < times; i++){
    		var node = document.createElement('span');
    		node.id = 'test' + i;
    		node.innerHTML = ' ';
    		node.lang = 234;
    		node.style.backgroundColor = 'black';
    		node.style.border = '1px solid black';
    		node.style.marginTop = '5px';
    		node.style.position = 'absolute';
    		node.style.left = '125px';
    		node.style.top = '50px';
    		node.style.width = '10px';
    		node.style.height = '10px';
    		parent.appendChild(node);
    	}
    	stat['normal_append']=new Date() - t;
    
    
    	/*******************	3	*******************/
    	t = new Date();
    	for (i = 0; i < times; i++){
    		appendElement2('span', {id: 'test' + i, lang:234, innerHTML: ' '}, 'background-color:black; border:1px solid black; margin:5px; font-size:10px; position:absolute; left:125px; top:50px; width:10px; height:10px', parent);
    	}
    	stat['new_appendFunction_with_cssText']=new Date() - t;
    
    	/*******************	4	*******************/
    	t = new Date();
    	for (i = 0; i < times; i++){
    		var node = document.createElement('span');
    		node.id = 'test' + i;
    		node.innerHTML = ' ';
    		node.lang = 234;
    		node.style.cssText = 'background-color:black; border:1px solid black; margin:5px; font-size:10px; position:absolute; left:125px; top:50px; width:10px; height:10px';
    		parent.appendChild(node);
    	}
    	stat['normal_append_with_cssText']=new Date() - t;
    
    
    	/*******************	5	*******************/
    	t = new Date();
    	for (i = 0; i < times; i++){
    		appendElement3('span', 'id="test'+i+'" lang=234', ' ', 'background-color:black; border:1px solid black; margin:5px; font-size:10px; position:absolute; left:125px; top:50px; width:10px; height:10px', parent);
    	}
    	stat['htmlParts']=new Date() - t;
    
    	/*******************	6	*******************/
    	t = new Date();
    	for (i = 0; i < times; i++){
    		appendElement4('<span id="test'+i+'" lang=234 style="background-color:black; border:1px solid black; margin:5px; font-size:10px; position:absolute; left:125px; top:50px; width:10px; height:10px"> </span>', parent);
    	}
    	stat['html_with_createElement_innerHTML']=new Date() - t;
    
    
    	/*******************	7	*******************/
    	t = new Date();
    	for (i = 0; i < times; i++){
    		appendElement5('<span id="test'+i+'" lang=234 style="background-color:black; border:1px solid black; margin:5px; font-size:10px; position:absolute; left:125px; top:50px; width:10px; height:10px"> </span>', parent);
    	}
    	stat['html_only_with_parentNode_InnerHTML']=new Date() - t;
    
    	document.write('<table>');
    	for(i in stat)
    		document.write('<tr><th>'+i+'</th><td>'+stat[i]+'</td></tr>');
    	document.write('</table>');
    }
    </script>
    </body>
    </html>

    Beispiel-Ausgabe (ff, die Zahlen dürften dem Durchschnitt in etwa entsprechen):

    Code:
    old_appendFunction			32
    old_appendFunction_with_cssNotations	27
    normal_append				24
    new_appendFunction_with_cssText		23
    normal_append_with_cssText		22
    htmlParts				21
    html_with_createElement_innerHTML	20
    html_only_with_parentNode_InnerHTML	24

    Ps
    Danke für eure Hilfe

    PPs
    Und nochmal danke fürs Video. War sehr informativ
    Geändert von Jodli (26-04-2011 um 20:11 Uhr) Grund: Beispielausgabe hinzugefügt

  10. #10
    ein schlauer ist offline Lounge-Member
    registriert
    18-08-2004
    Beiträge
    14.671

    AW: bestehendes Object einer Klasse "zuweisen"

    Ich hab die Anzahl mal erhöht (und bei 2000 gleich mal einen Absturz im FF) auf 1000 und die Ausgabe sortiert:

    Alles unter Ubuntu (64Bit)

    FF 3.6
    Code:
    old_appendFunction	241
    old_appendFunction_with_cssNotations	273
    normal_append	312
    new_appendFunction_with_cssText	336
    normal_append_with_cssText	379
    htmlParts		415
    html_with_createElement_innerHTML	469
    html_only_with_parentNode_InnerHTML	1259
    Epiphany (Webkit )
    Code:
    normal_append_with_cssText	23
    new_appendFunction_with_cssText	25
    html_with_createElement_innerHTML	29
    normal_append	30
    htmlParts			30
    old_appendFunction_with_cssNotations	34
    old_appendFunction	41
    html_only_with_parentNode_InnerHTML	53
    Opera
    Code:
    html_only_with_parentNode_InnerHTML	32
    old_appendFunction	38
    normal_append	45
    new_appendFunction_with_cssText	46
    html_with_createElement_innerHTML	48
    old_appendFunction_with_cssNotations	49
    normal_append_with_cssText	50
    htmlParts		51
    Ich hab mir die Benchmarks nicht genauer angeschaut, dass ist ja immer so ein heikle Sache, was hier wirklich "gebenchmarked" wird. Oft sind die Nebeneffekte das entscheidene. Aber so wie's aussieht kannst du mit der "normal_append" Funktion nichts falsch machen.

    Eine Überlegung Wert, wäre noch ein DocumentFragment, wenn du viele Knoten einfügen willst. John Resig hat das mal hier beschrieben: http://ejohn.org/blog/dom-documentfragments/ - Wie aber schon gesagt, das entscheidene dürften nicht die Schleifen sein, sondern das erzeugen des jeweiligen DOM Objekts und das einfügen.

Ähnliche Themen

  1. Antworten: 2
    Letzter Beitrag: 30-01-2008, 23:51
  2. Antworten: 0
    Letzter Beitrag: 06-01-2008, 23:35
  3. Antworten: 4
    Letzter Beitrag: 11-12-2007, 09:47
  4. Antworten: 12
    Letzter Beitrag: 22-10-2003, 03:20
  5. Antworten: 6
    Letzter Beitrag: 22-05-2003, 11:20

Stichworte

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •