Javascript - getter Eigenschaft ist undefined – SELFHTML-Forum Forum als Ergänzung zum SELFHTML-Wiki und zur Dokumentation SELFHTML https://forum.selfhtml.org/self Javascript - getter Eigenschaft ist undefined Mon, 13 Dec 21 13:09:53 Z https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794413#m1794413 https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794413#m1794413 <p>Hallo,</p> <p>eine Klasse <code>Movies</code> erfasst das anklicken von Checkboxen und fügt den Inhalt in ein Objekt, welches als Wert in <code>set filter({}</code>) gespeichert wird.</p> <p>Ein Klick auf einen Button gibt den Wert von <code>get filter()</code> aus. Hier ist Movies.filter aber <code>undefined</code>.</p> <p>Innerhalb der Methode Movies.saveSelection() gebe ich Movies.filter ebenfalls aus und hier enthält Movies.filter auch den richtigen Wert.</p> <p><strong>Warum nicht innerhalb der Funktion <code>menuShow()</code>?</strong></p> <p>Gruß ebody</p> Javascript - getter Eigenschaft ist undefined Mon, 13 Dec 21 13:33:08 Z https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794415#m1794415 https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794415#m1794415 <p>Hallo,</p> <p>this zeigt in Eventhandlern nicht auf die Klasse, sondern auf das eventauslösende Element. Wir hatten das erst vor kurzem:</p> <p><a href="https://forum.selfhtml.org/self/2021/nov/24/manoverkritik-oop-in-js/1794077#m1794077" rel="noopener noreferrer">https://forum.selfhtml.org/self/2021/nov/24/manoverkritik-oop-in-js/1794077#m1794077</a></p> <p>Gruß<br> Jürgen</p> Javascript - getter Eigenschaft ist undefined Tue, 14 Dec 21 00:14:05 Z https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794434#m1794434 https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794434#m1794434 <p>Tach!</p> <p>Deine Frage wurde schon beantwortet. Hier kommen weitere Anmerkungen.</p> <blockquote> <pre><code class="block language-js"> <span class="token keyword">set</span> <span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">objFilter<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>objFilter <span class="token operator">=</span> objFilter<span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> </blockquote> <p>Ein Setter kann keine optionalen Parameter haben. Das ergibt auch keinen Sinn. Der Setter wird per Zuweisung aufgerufen und niemals ohne eine solche. Also ist ein Wert für den Parameter zwingend vorhanden. Wenn das eine Initialisierung von <code>this.objFilter</code> sein sollte, so kann das im Konstruktor erfolgen.</p> <blockquote> <pre><code class="block language-js"> <span class="token keyword">let</span> objFilterCollection <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre> </blockquote> <p>Das ist die einzige Zuweisung an diese Variable. Sie kann deshalb als <code>const</code> deklariert werden. Die Referenz auf das Objekt bleibt konstant, die Änderungen an seinem Inhalt ändern daran nichts.</p> <p>Für alle anderen Stellen, an denen du <code>let</code> verwendest, ergibt sich ebenfalls keine Notwendigkeit. Alle Variableninhalte bleiben unverändert.</p> <p>dedlfix.</p> Javascript - getter Eigenschaft ist undefined Mon, 13 Dec 21 16:13:24 Z https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794423#m1794423 https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794423#m1794423 <p>Hallo Jürgen,</p> <p>vielen Dank für den Hinweis.</p> <p>Ich habe jetzt vor dem Eventhandler <code>this</code> in einer Variablen <code>that</code> gespeichert und kann so auf Methoden innerhalb des Eventhandlers und der Klasse zugreifen. <a href="https://stackoverflow.com/questions/43727516/how-adding-event-handler-inside-a-class-with-a-class-method-as-the-callback/43727582#43727582" rel="noopener noreferrer">Quelle.</a></p> <pre><code class="block language-javascript"><span class="token keyword">let</span> that <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span> element<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'change'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">evt</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> that<span class="token punctuation">.</span>filter <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>Gruß ebody</p> Javascript - getter Eigenschaft ist undefined Mon, 13 Dec 21 17:38:46 Z https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794427#m1794427 https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794427#m1794427 <p>Hallo ebody,</p> <p>nein, ein <code>that</code> ist eine Krücke. Eine Krücke mit Tradition, aber trotzdem eine Krücke.</p> <p>In einem function-Eventhandler ist <code>this</code> das <code>currentTarget</code> des Events. D.h. das Element, auf dem <code>addEventListener</code> aufgerufen wurde. Das kann mit <code>target</code> übereinstimmen, muss aber nicht, wenn bubbling stattfindet.</p> <p>Es ist demnach schwer verständlich, im change-Eventhandler <code>this</code> zu verwenden und damit das DOM Element zu meinen, in dem der change stattfand. Es ist noch schwerer verständlich, wenn man <code>this</code> und <code>event.target</code> gleichzeitig verwendet. Dein 4 Monate älteres Ich fragt sich dann um Ostern rum: Was hat der verfluchte Kerl da kurz vor Weihnachten nur getan? Warum mal <code>this</code>, warum mal <code>event.target</code> - was war die Notwendigkeit dafür?!?!?! Gibt keine. Verwende immer <code>event.target</code>.</p> <p>Bei Dir kommt verschärfend hinzu, dass der Eventhandler eine lokale Funktion in einer Methode ist. In einem solchen Umfeld verbinde ich <code>this</code> eigentlich automatisch mit dem Objekt, zu dem die Methode gehört. Darf ich in dem Moment aber nicht. Ich muss ständig nachdenken, wofür jetzt <code>this</code> steht. Und das ist Mist. Jedes Nachdenken über die richtige Bedeutung ist einmal zu viel nachgedacht.</p> <p>Weiteres Problem: Du registrierst die change-Handler in einer Schleife auf jeder Checkbox einzeln. Lass das. Registriere den Handler nur einmal, auf #chipsbox. Die <code>change</code> Events entstehen auf den Checkboxen und blubber von da aus im DOM nach oben. Wenn sie am chipsbox-div vorbeikommen, kannst Du sie mit einer einzigen Eventhandler Registrierung behandeln und kannst Dir die Registrierschleife sparen.</p> <p>Um das this-Problem zu lösen, kannst Du - aus Lesbarkeitsgründen - die Handlerfunktion separat aufschreiben und als Eventhandler die an this gebundene Funktion übergeben. Oder du kannst sie gleich als Pfeilfunktion notieren, dann entsteht keine neue this-Bindung und du verwendest automatisch das this des Eltern-Scopes.</p> <pre><code class="block language-js"><span class="token function">saveSelection</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> objFilterCollection <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> chipsBox <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'chipsBox'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> chipsBox<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span> <span class="token string">'change'</span><span class="token punctuation">,</span> <span class="token parameter">event</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// Handle on</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>Nächster Punkt: An Arrays herumzufummeln, um einzeln Werte reinzuschieben oder rauszuholen, ist lästig, mühsam, fehlerträchtig. Kurz: sollte man lassen. Viel einfacher ist es, das Array bei jeder Änderung neu aufzubauen. Dabei kann man sich sogar noch von einem CSS Selektor helfen lassen - die aktiven Checkboxen kriegst Du mit querySelectorAll("input[type=checkbox]:checked").</p> <p>Wenn Du dann noch alle Checkboxen zu einem Thema in ein Fieldset kapselst, kannst Du den Key ans Fieldset stellen und brauchst ihn nicht an jede Checkbox zu schreiben. Dorthin kommen nur die Values. Und die auch nicht als data, sondern als value-Attribut. Dafür gibt's das schließlich. WENN Du unbedingt den Key an der Checkbox haben willst - nagut, steck ihn in's name-Attribut. Wenn Du das in einem Form hast und an einen PHP Server submitten willst, dann mit name="Genre[]" oder so, damit das Checkboxarray am Server auch als Array ankommt. Aber solange Du das nur in JavaScript machst, ohne Server, brauchst Du Dich um ein name Attribut der Checkboxen nicht zu kümmern.</p> <p><a href="https://jsfiddle.net/Rolf_b/co2ngmvs/" rel="noopener noreferrer">Meine Idee zum Thema</a></p> <p>Der komplexeste Teil in meinem Fiddle sind vermutlich diese beiden Zeilen:</p> <pre><code class="block language-js"><span class="token keyword">const</span> keySet <span class="token operator">=</span> container<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">input[type=checkbox]:checked</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>filters<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token class-name">Array</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>keySet<span class="token punctuation">,</span> <span class="token parameter">checkbox</span> <span class="token operator">=></span> checkbox<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>Aber dafür übernehmen die auch den größten Teil deines Scripts. Zeile 1: container ist eine Variable, die auf das fieldset zeigt. Mit querySelectorAll suche ich im fieldset alle checkboxen, die checked sind. Das Ergebnis ist eine NodeList.</p> <p>Eine NodeList ist kein Array, deshalb hat sie keine map-Methode. Aber sie ist array-artig genug, um sie der map-Methode von Array.prototype als Array unterzuschieben (dafür braucht's nur eine length-Eigenschaft und Werte, die mit 0,1,2,3... indexiert sind).</p> <p><code>Array.prototype.map.call</code></p> <p>tut genau das. <code>call</code> ist eine Methode, die jedes Function-Objekt hat. Man kann sie damit aufrufen und einen Wert für <code>this</code> festlegen. Ich verwende damit also die map-Methode der Arrays für die NodeList, die in keySet steht. Die map-Methode bekommt einen Callback, der auf jedes Array-Element angewendet wird, und das Ergebnis ist ein Array mit den Ergebnissen. D.h. ich bekomme ein Array mit den value-Werten aller Checkboxen, die angehakt sind. Und das speichere ich in this.filters[key]. Wenn da vorher schon was stand, egal, weg damit, ist veraltet.</p> <p>So kurz und knackig kann das gehen </p> <p><em>Rolf</em></p> <div class="signature">-- <br> sumpsi - posui - obstruxi </div> Javascript - getter Eigenschaft ist undefined Tue, 14 Dec 21 00:25:28 Z https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794435#m1794435 https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794435#m1794435 <p>Tach!</p> <blockquote> <p>Eine NodeList ist kein Array, deshalb hat sie keine map-Methode. Aber sie ist array-artig genug, um sie der map-Methode von Array.prototype als Array unterzuschieben (dafür braucht's nur eine length-Eigenschaft und Werte, die mit 0,1,2,3... indexiert sind).</p> <p><code>Array.prototype.map.call</code></p> <p>tut genau das.</p> </blockquote> <p>Einfacher und mehr gerade heraus ist es, ein echtes Array draus zu machen. Das schreibt sich auch kürzer.</p> <pre><code class="block language-js"><span class="token keyword">this</span><span class="token punctuation">.</span>filters<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>keySet<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">checkbox</span> <span class="token operator">=></span> checkbox<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p>dedlfix.</p> Javascript - getter Eigenschaft ist undefined Tue, 14 Dec 21 17:59:49 Z https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794482#m1794482 https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794482#m1794482 <p>Hallo Rolf,</p> <p>vielen Dank für die vielen guten Hinweise und Tipps!</p> <p>Gruß ebody</p> Javascript - getter Eigenschaft ist undefined Tue, 14 Dec 21 08:05:05 Z https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794437#m1794437 https://forum.selfhtml.org/self/2021/dec/13/javascript-getter-eigenschaft-ist-undefined/1794437#m1794437 <p>Hallo dedlfix,</p> <p>gute Idee. An den <a href="https://wiki.selfhtml.org/wiki/JavaScript/Operatoren/Rest-_oder_Spread-Operator" rel="nofollow noopener noreferrer">... Operator</a> zum umkopieren eines arrayoiden Dings (oder gar iterierbaren Dings? Müsste ich jetzt recherchieren) in ein Array hab ich mich noch icht gewöhnt.</p> <p>(Zurück aus dem Wiki) - ja, iterierbar reicht.</p> <p><em>Rolf</em></p> <div class="signature">-- <br> sumpsi - posui - obstruxi </div>