René Tumbrink: Objekt erwartet, in Zeile eines Funktionsaufrufes

Hallo zusammen,

ich habe ein kleines Problem mit folgendem Script. Habe das ganze für euch aus Platzgründen etwas gekürzt, führt aber weiterhin zu selbigem Problem. Und zwar funktioniert das ganze im Firefox tadellos aber im IE bekomme ich nur ne Fehlermeldung Objekt erwartet. Als Zeile wird die des Funktionsaufrufes (hier in der vorletzten Zeile) angegeben.

Woran könnte dies liegen?

<script type="text/javascript">
function fill_classes(value) {

for (var i=document.char_create.class.length; i > 0; i--) {
    document.char_create.class.options[document.char_create.class.length - 1] = null;
  }

race = new Array();
race[1] = new Array();
race[1][0] = "Dummy-Wert10"
race[1][1] = "Dummy-Wert11"
race[1][2] = "Dummy-Wert12"
race[1][3] = "Dummy-Wert13"
race[1][4] = "Dummy-Wert14"
race[2] = new Array();
race[2][0] = "Dummy-Wert20"
race[2][1] = "Dummy-Wert21"
race[2][2] = "Dummy-Wert22"
race[2][3] = "Dummy-Wert23"

temp = race[value];

for (var i=0; i<temp.length; i++) {
  add_class = new Option(temp[i]);
  document.char_create.class.options[document.char_create.class.length] = add_class;
}

}
</script>

<select name="race" onChange="fill_Classes(this.value)"><option value="1">Wert1</option><option value="2">Wert2</option></select><br>
<select name="class"><option value="0"></option></select>

  1. Oh da hab ich was zu viel rausgenommen.

    Um die Selects liegt noch eine Form

    <form name="char_create">
    </form>

  2. Hi,

    "this" bezieht sich auf das aktuelle Formular, was wohl nicht erwünscht ist:
    <select name="race" onChange="fill_Classes(this.value)">

    Wenn das Formularfeld "race" gemeint ist, muss es heißen
    <select name="race" onChange="fill_Classes(this.form.race.value)">

    Gruß, Don P

    1. Hi,

      "this" bezieht sich auf das aktuelle Formular, was wohl nicht erwünscht ist:
      <select name="race" onChange="fill_Classes(this.value)">

      Wenn das Formularfeld "race" gemeint ist, muss es heißen
      <select name="race" onChange="fill_Classes(this.form.race.value)">

      Gruß, Don P

      Hmm, habe es auf deine Antwort hin, mit folgenden Versionen probiert.

      <select name="race" onChange="fill_classes(this.form.race.value)">
      <select name="race" onChange="fill_classes(this.char_create.race.value)">
      <select name="race" onChange="fill_classes(document.char_create.race.value)">

      Probiert. Funktioniert alles nicht :(

      1. Okay das Problem hat sich erledigt.

        Habe einen Klassenkameraden aus der Berufsschule gefragt.

        Man darf das select nicht class nennen.

        also

        <select name="class"> geht nicht
        hab es dann auf <select name="nc_class"> geändert.

        Nun klappt es.

        Trotzdem danke.

        1. Man darf das select nicht class nennen.

          Natürlich darf man das, du kannst es dann nur nicht über formular.class ansprechen, sondern musst den Indexoperator verwenden.
          formular.elements['class']

          Struppi.

        2. Ach ja, manchmal sieht man den Wald vo lauter Bäumen nicht.
          JavaScript hat leider viel zu viele "reserved words".
          Die meisten davon werden in der Sprache gar nicht benutzt, sind aber unverständlicherweise trotzdem verboten....

          Don P

          1. Grütze .. äh ... Grüße!

            JavaScript hat leider viel zu viele "reserved words".
            Die meisten davon werden in der Sprache gar nicht benutzt, sind aber unverständlicherweise trotzdem verboten....

            Ist sehr sinnvoll. Wie sonst soll man auch JS weiterentwickeln können? Wenn die reserved words erst dann verboten werden würden, wenn sie wirklich belegt sind, dann gäbe es Unmengen Scripts, die genau dann heftig auf die Schnauze fallen würden.


            Kai

            --
            Der vertuschte Gefahrstoff: Dihydrogenmonoxid
               +---------+
               |   __    |
            ---+--|_R|---+---- Widerstand ist zwecklos
            ie:{ fl:( br:< va:) ls:? fo:| rl:? n4:° ss:{ de:] js:| ch:? mo:| zu:|
    2. "this" bezieht sich auf das aktuelle Formular, was wohl nicht erwünscht ist:
      <select name="race" onChange="fill_Classes(this.value)">

      Nein das ist falsch, this bezieht sich auf das aktuelle Element.

      Wenn das Formularfeld "race" gemeint ist, muss es heißen
      <select name="race" onChange="fill_Classes(this.form.race.value)">

      das ist ein Umweg und wenn müßte so heißen:

      <select name="race" onChange="fill_Classes(this.options[this.selectedIndex].value)">  
      
      

      Struppi.

      1. Tatsächlich?
        Könnte sein, weil es noch Options gibt.
        Jedenfalls ist es nicht immer intuitiv klar, was "this" genau ist. Siehe [url]http://de.selfhtml.org/javascript/sprache/objekte.htm#this[/url]

        So, wie es dort beschrieben ist, bezieht sich "this" irgendwie auf das document-Objekt, aber "this.form" auf das aktuelle Formular (wie auch immer dieses heißt), nicht etwa auf das aktuelle Formularfeld...

        Ich persönlich vermeide deshalb "this" bzgl. des DOM.

        Don P

        1. Tatsächlich?

          Ja.

          Jedenfalls ist es nicht immer intuitiv klar, was "this" genau ist. Siehe [url]http://de.selfhtml.org/javascript/sprache/objekte.htm#this[/url]

          So, wie es dort beschrieben ist, bezieht sich "this" irgendwie auf das document-Objekt, aber "this.form" auf das aktuelle Formular (wie auch immer dieses heißt), nicht etwa auf das aktuelle Formularfeld...

          this bezieht sich immer auf das aktuelle Objekt in dessen Kontext eine Funktion aufgerufen wird.
          In this.form bezieht (inerhalb z.b. eines input Elements) sich this auf das Element und die Eigenschaft form ist die Referenz auf das Formular

          Ich persönlich vermeide deshalb "this" bzgl. des DOM.

          Man kann this nicht vermeiden, z.b. wenn man mit Objekten Arbeitet auch in Eventhandlern ist this sehr nützlich und was du mit "bzgl. des DOM" meinst ist mir nicht klar.

          Struppi.

          1. this bezieht sich immer auf das aktuelle Objekt in dessen Kontext eine Funktion aufgerufen wird.
            In this.form bezieht (inerhalb z.b. eines input Elements) sich this auf das Element und die Eigenschaft form ist die Referenz auf das Formular

            Aha, wieder was gelernt, danke.

            Man kann this nicht vermeiden, z.b. wenn man mit Objekten Arbeitet auch in Eventhandlern ist this sehr nützlich und was du mit "bzgl. des DOM" meinst ist mir nicht klar.

            mit "bzgl. des DOM" (=Document Object Model) meine ich, dass man mit "this" ein Element im HTML-Baum anspricht, wie z.B. in unserem Fall ein Formularelement oder sowas.

            Innerhalb von reinen JavaScript-Objekten bzw. -Funktionen ist meistens klar, was "this" ist, aber JavaScript macht sogar dort Fehler, nämlich in sog. closures (eingebetten Funktionen).

            Gruß, Don P

            1. mit "bzgl. des DOM" (=Document Object Model) meine ich, dass man mit "this" ein Element im HTML-Baum anspricht, wie z.B. in unserem Fall ein Formularelement oder sowas.

              hmmm? du meinst als Parameter in einem Event onevent="Func(this)" ansonsten spielt es da erstmal eine untergeordnete Rolle.

              Innerhalb von reinen JavaScript-Objekten bzw. -Funktionen ist meistens klar, was "this" ist, aber JavaScript macht sogar dort Fehler, nämlich in sog. closures (eingebetten Funktionen).

              Inwiefern Fehler?
              Wie gesagt es spielt immer der Kontext eine Rolle. Du meinst sowas?

              function Obj() {  
               var closure = function() {  
               alert(this);  
               }  
               closure();  
              }  
                
              new Obj();  
              
              

              Hier erfolgt der Aufruf des closure im window Kontext, folgerichtig ist this = window

              Das kannst du z.b. so umgehen:

              function Obj() {  
               var closure = function() {  
               alert(this);  
               }  
               closure.call(this);  
              }  
                
              new Obj(); 
              

              Struppi.

              1. hmmm? du meinst als Parameter in einem Event onevent="Func(this)" ansonsten spielt es da erstmal eine untergeordnete Rolle.

                Ja, das meine ich. Aber vielleicht kommt es nur daher, dass ich das Browser-DOM anscheinend zu wenig kenne, sonst hätte ich ja merken müssen, dass bei this.form das übergeordnete Element (Formular) gemeint ist.

                Innerhalb von reinen JavaScript-Objekten bzw. -Funktionen ist meistens klar, was "this" ist, aber JavaScript macht sogar dort Fehler, nämlich in sog. closures (eingebetten Funktionen).

                Inwiefern Fehler?
                Wie gesagt es spielt immer der Kontext eine Rolle. Du meinst sowas?

                function Obj() {

                var closure = function() {
                alert(this);
                }
                closure();
                }

                new Obj();

                  
                Genau.  
                  
                
                > Hier erfolgt der Aufruf des closure im window Kontext, folgerichtig ist this = window  
                  
                Eben gerade nicht: Der Aufruf "closure();" erfolgt im Obj-Kontext (innerhalb des Objekts "Obj"), folgerichtig müsste "this" innnerhalb der closure auf Obj verweisen, tut es aber nicht, und das ist genau der Fehler, bzw. schwächer formuliert, eine Inkonsequenz.  
                  
                Zitat Douglas Crockford (eine JavaScript-Koryphäe):  
                "In a simple function call,  this is set to the Global Object (aka window), which is not very useful. The correct behavior should have been to preserve the current value of this, particularly when calling inner functions."  
                  
                Der Aufruf "closure();" ist ein solcher simple function call, und "this" zeigt in diesem Fall immer auf das sog. globale Objekt, d.h. das window-Objekt im Browser-DOM.  
                  
                Don P
                
                1. Eben gerade nicht: Der Aufruf "closure();" erfolgt im Obj-Kontext (innerhalb des Objekts "Obj"), folgerichtig müsste "this" innnerhalb der closure auf Obj verweisen, tut es aber nicht, und das ist genau der Fehler, bzw. schwächer formuliert, eine Inkonsequenz.

                  Das kann man bemäkeln, aber jeder Aufruf einer Funktion in einer Funktion erfolgt im window Kontext, von daher ist es OK.

                  Zitat Douglas Crockford (eine JavaScript-Koryphäe):

                  Du kennst dich aus ;-)

                  "In a simple function call,  this is set to the Global Object (aka window), which is not very useful. The correct behavior should have been to preserve the current value of this, particularly when calling inner functions."

                  wie gesagt, da kann man sicher drüber steiten, aber vielleicht hat es auch einen Grund, der sich mir und dir (und Douglas) nicht erschliesst.
                  Aber es läßt sich ja leicht beheben, wie ich dir gezeigt hatte.

                  Der Aufruf "closure();" ist ein solcher simple function call, und "this" zeigt in diesem Fall immer auf das sog. globale Objekt, d.h. das window-Objekt im Browser-DOM.

                  Ja, wie alle Funktionen, die du Ohne Objekt aufrufst, aber dafür gibt es ja dann .call()

                  Struppi.

                  1. Jaja, ich kenn' mich aus, gelle da staunst du ;)

                    Ja, wie alle Funktionen, die du Ohne Objekt aufrufst, aber dafür gibt es ja dann .call()

                    Sowas nennt man glaub' "Salt", eine unbequeme Sache, deren Sinn sich niemandem recht erschließt. Unbequem deshalb, weil man extra .call() bemühen muss für etwas, das in anderen Zusammenhängen ganz problemlos einfach nur funktioniert.

                    Ich gehe noch weiter und nenne es einen Fehler in der Programmiersprache. Wenn man das globale Objekt ausnahmsweise mal wirklich meint, kann man es auch direkt ansprechen, sofern es überhaupt einen Namen hat ("window"). Eigentlich hat es ja keinen...

                    Preisfrage:
                    Welches Statement ist schneller: "window.document" oder nur "document"?

                    1. Ja, wie alle Funktionen, die du Ohne Objekt aufrufst, aber dafür gibt es ja dann .call()

                      Sowas nennt man glaub' "Salt", eine unbequeme Sache, deren Sinn sich niemandem recht erschließt. Unbequem deshalb, weil man extra .call() bemühen muss für etwas, das in anderen Zusammenhängen ganz problemlos einfach nur funktioniert.

                      Ich gehe noch weiter und nenne es einen Fehler in der Programmiersprache. Wenn man das globale Objekt ausnahmsweise mal wirklich meint, kann man es auch direkt ansprechen, sofern es überhaupt einen Namen hat ("window"). Eigentlich hat es ja keinen...

                      http://www.ecma-international.org/publications/standards/Ecma-262.htm
                      Ich tu mich schwer damit

                      Für diesen Fall scheint mir der Absatz relevant zu sein:

                      Function Code (10.2.3)

                      [..]

                      • The caller provides the this value. If the this value provided by the caller is not an object (including

                      the case where it is null), then the this value is the global object.

                      Aber ehrlich gesagt verstehe ich das nicht genau. Fakt ist aber, dass das closure nicht an this gebunden wird.

                      Preisfrage:
                      Welches Statement ist schneller: "window.document" oder nur "document"?

                      Das ist mir auch schon über den Weg gelaufen, weißt du auch warum?
                      Die Seiten die ich zu "JS optimization" gefunden habe, empfehlen alle window.document

                      Struppi.

                      1. http://www.ecma-international.org/publications/standards/Ecma-262.htm
                        Ich tu mich schwer damit

                        Für diesen Fall scheint mir der Absatz relevant zu sein:

                        Function Code (10.2.3)
                        [..]
                        • The caller provides the this value. If the this value provided by the caller is not an object (including
                        the case where it is null), then the this value is the global object.

                        Aber ehrlich gesagt verstehe ich das nicht genau. Fakt ist aber, dass das closure nicht an this gebunden wird.

                        Ja, das habe ich nochmal explizit nachvollzogen, mit fogendem Code:
                        <script>
                        function Jemand( werDenn ) {

                        alert ( '(this===window) in neuem Objekt: ' + (this===window) );

                        var selbst = this;

                        this.name = werDenn;
                         this.biste = function() {

                        alert ( '(this===window) in Methode: ' + (this===window) );

                        this.name = "Mr.Spock";

                        meinName = function () {

                        alert ( '(this===window) in innerer Funktion: ' + (this===window) );

                        //return this.name;
                           return selbst.name;
                          }

                        return meinName();
                         }
                        }
                        var wer = new Jemand( 'Vulkanier' );
                        alert( "Hallo " + wer.name +"!" );
                        alert( "Hallo " + wer.biste() +"!" );

                        </script>

                        Wie man sieht, funktioniert "this" in der öffentlichen Variablen "name" und der öffentlichen Methode "biste" des Objekts "Jemand" genau so, wie es sich gehört.
                        In der inneren Funktion "meinName()" aber, ist "this" plötzlich das globale Objekt (in der auskommentierten Zeile), denn diese Funktion wird mit "return meinName();" direkt aufgerufen.

                        Man kann das Problem eleganter als mit .call() umschiffen, indem man (vorsichtshalber grundsätzlch in jedem Objekt) eine private Variable "selbst" definiert, die dann in inneren Funktionen an Stelle des kaputten "this" benutzt wird.

                        Ich bin mir nicht sicher, aber ein denkbarer Grund  für dieses unbequeme Verhalten könnte sein, dass die vordefinierten JavaScript-Objekte und Funktionen wie "Object", "String", aber auch "new", "alert" usw. ja alle auch nur Unterobjekte des globalen Objekts sind. Diese werden immer direkt aufgerufen. Wenn "this" auch in einer direkt aufgerufenen Funktion immer auf den aktuellen Kontext verweisen würde, statt auf das globale Objekt, dann würde JavaScript vielleicht seine eigene Sprache nicht mehr verstehen. Ein "irgendwas.alert()" ist ja normalerweise nicht definiert.
                        Aber das ist reine Spekulation. Genauso gut könnte es sein, dass es sich einfach um eine Nachlässigkeit in der urprünglichen Implementierung handelt, die man später auch in der Spezifikation nicht mehr zu bereinigen wagte, um bestehende Programme nicht zu gefährden. Das ist z.B. im Fall der fehlerhaften typeof-Funktion  bekanntermaßen so.

                        Preisfrage:
                        Welches Statement ist schneller: "window.document" oder nur "document"?

                        Das ist mir auch schon über den Weg gelaufen, weißt du auch warum?
                        Die Seiten die ich zu "JS optimization" gefunden habe, empfehlen alle window.document

                        Nein, "window.document" ist umständlicher, weil "window" lediglich auf das ansonsten namenlose globale Objekt verweist.
                        Wenn man nur "document" sagt, ist klar, das es eine Eigenschaft oder Methode des globalen Objekts ist. Der Compiler kann sofort dort nachschauen.
                        Beim Ausdruck "window.document" dagegen sucht der Compiler erst im globalen Objekt nach "window", wird dann erneut auf das globale Objekt verwiesen, wo er erst dann das document-Objekt finden kann.

                        Gruß, Don P

                        1. <script>
                          function Jemand( werDenn ) {

                          alert ( '(this===window) in neuem Objekt: ' + (this===window) );

                          var selbst = this;

                          this.name = werDenn;
                          this.biste = function() {

                          alert ( '(this===window) in Methode: ' + (this===window) );

                          this.name = "Mr.Spock";

                          meinName = function () {

                          Naja, meinName ist in deinem Fall eine Funktion des globalen Objektes, wobei aber ein var davor für die Fragstellung keinen Unterschied macht.

                          In der inneren Funktion "meinName()" aber, ist "this" plötzlich das globale Objekt (in der auskommentierten Zeile), denn diese Funktion wird mit "return meinName();" direkt aufgerufen.

                          Also nicht im Kontext des Objektes (this), folglich muss this in der Funktion das globale Objekt sein.

                          Man kann das Problem eleganter als mit .call() umschiffen, indem man (vorsichtshalber grundsätzlch in jedem Objekt) eine private Variable "selbst" definiert, die dann in inneren Funktionen an Stelle des kaputten "this" benutzt wird.

                          Jaja, ich weiß, ob es eleganter ist eine zusätzlich Variabel einzuführen sei aber mal dahin gestellt, ich mache das aber auch meistens so.

                          Aber das ist reine Spekulation. Genauso gut könnte es sein, dass es sich einfach um eine Nachlässigkeit in der urprünglichen Implementierung handelt, die man später auch in der Spezifikation nicht mehr zu bereinigen wagte, um bestehende Programme nicht zu gefährden. Das ist z.B. im Fall der fehlerhaften typeof-Funktion  bekanntermaßen so.

                          Was ist da fehlerhaft?
                          Ich hab gesucht und konnte keinen Hinweis darauf finden.

                          Preisfrage:
                          Welches Statement ist schneller: "window.document" oder nur "document"?

                          Das ist mir auch schon über den Weg gelaufen, weißt du auch warum?
                          Die Seiten die ich zu "JS optimization" gefunden habe, empfehlen alle window.document

                          Nein, "window.document" ist umständlicher, ...

                          Das wollte ich damit sagen, aber seltsamerweise findest du auf allen möglichen Seite über JS Optimierung genau die andere Variante als Empfehlung. Danke für die Erläuterung klingt logisch.

                          Struppi.

                          1. <script>
                            function Jemand( werDenn ) {

                            alert ( '(this===window) in neuem Objekt: ' + (this===window) );

                            var selbst = this;

                            this.name = werDenn;
                            this.biste = function() {

                            alert ( '(this===window) in Methode: ' + (this===window) );

                            this.name = "Mr.Spock";

                            meinName = function () {

                            Naja, meinName ist in deinem Fall eine Funktion des globalen Objektes, wobei aber ein var davor für die Fragstellung keinen Unterschied macht.

                            OOops, da hab' ich doch glatt das var davor vergessen. Aber stimmt, es macht hier keinen Unterschied, weil ein Ausdruck "var meinName = function() {...}" immer synonym ist zu "function meinName() {...}".

                            Dass es aber eine Funktion des globalen Objekts ist, stimmt definitiv nicht! Es ist hier eine "innere" Funktion von biste(). Wäre es eine globale, dann könnte man sie auch von außerhalb des Objekts "Jemand" oder von außerhalb der Funktion "biste()" aufrufen, was natürlich nicht möglich ist.

                            In der inneren Funktion "meinName()" aber, ist "this" plötzlich das globale Objekt (in der auskommentierten Zeile), denn diese Funktion wird mit "return meinName();" direkt aufgerufen.

                            Also nicht im Kontext des Objektes (this), folglich muss this in der Funktion das globale Objekt sein.

                            Im Kontext des Objekts "biste", wo sie überhaupt nur aufgerufen werden kann (siehe oben), also darf ihr "this" nicht das globale Objekt sein, was es aber leider ist.

                            Aber das ist reine Spekulation. Genauso gut könnte es sein, dass es sich einfach um eine Nachlässigkeit in der urprünglichen Implementierung handelt, die man später auch in der Spezifikation nicht mehr zu bereinigen wagte, um bestehende Programme nicht zu gefährden. Das ist z.B. im Fall der fehlerhaften typeof-Funktion  bekanntermaßen so.

                            Was ist da fehlerhaft?
                            Ich hab gesucht und konnte keinen Hinweis darauf finden.

                            Falsch ist z.B., dass "typeof null" den String 'object' zurückgibt. "null" ist kein objekt. In Javascript sind zwar fast alles Objekte, aber null gehört nicht dazu.
                            "typeof []" gibt ebenfalls 'object' als Typ für ein Array zurück, was zwar in gewisser Weise stimmt, aber unbrauchbar ist, es sollte  'array' zurückgegeben werden.

                            Gruß, donp

                            1. OOops, da hab' ich doch glatt das var davor vergessen. Aber stimmt, es macht hier keinen Unterschied, weil ein Ausdruck "var meinName = function() {...}" immer synonym ist zu "function meinName() {...}".

                              Innerhalb der Funktion ja, aber der Unterschied von
                              var meinName = function() {...}
                              meinName = function() {...}

                              innerhalb der funktion ist gross und darum ging es

                              Dass es aber eine Funktion des globalen Objekts ist, stimmt definitiv nicht! Es ist hier eine "innere" Funktion von biste().

                              und sobald du biste() augeferufen hast ist es eine globale Funktion.

                              Wäre es eine globale, dann könnte man sie auch von außerhalb des Objekts "Jemand" oder von außerhalb der Funktion "biste()" aufrufen, was natürlich nicht möglich ist.

                              Du musst natürlich die globale Variabel meinName erst setzen bevor du sie vewrwenden kannst.

                              Struppi.

                              1. [...] aber der Unterschied von
                                var meinName = function() {...}
                                meinName = function() {...}

                                innerhalb der funktion ist gross und darum ging es

                                Groß? Wieso das denn? Es gibt keinen Unterschied. Gar keinen. Folgende Statements bewirken immer genau das gleiche:

                                function f() {...};
                                f = function() {...};
                                var f = function() {...};

                                Und zwar wird jeweils eine neue Funktion im aktuellen Kontext definiert. Geschieht das innerhalb eines Objekts (oder Funktion), dann handelt es sich um eine *private* Funktion dieses Objekts, die von außerhalb nicht aufgerufen werden kann. Im globalen Kontext ist es ebenfalls eine *private* Funktion, aber diesmal des globalen Objekts, was sie erst zur globalen Funktion macht.

                                Bei gewöhnlichen Variablen gibt es bekanntlich einen Unterschied zwischen z.B. "v=1;" und "var v=1;". Im ersten Fall wird immer eine globale Variable angelegt, im zweiten Fall immer eine private Variable im aktuellen Kontext.

                                Dass es aber eine Funktion des globalen Objekts ist, stimmt definitiv nicht! Es ist hier eine "innere" Funktion von biste().

                                und sobald du biste() augeferufen hast ist es eine globale Funktion.

                                Ähhäm... jetzt dämmert mir langsam was du meinst:
                                Weil man innere Funktionen nicht explizit mit "var" privatisieren kann (die Privatisierung geschieht ja automatisch, siehe oben), glaubt biste() immer, bei der inneren Funktion handele es sich um eine globale, und jubelt ihr deshalb das globale Objekt als "this" unter.
                                Das wäre logisch, aber ich halte es trotzdem für einen Fehler in der Konzeption. Der Compiler erkennt ja, dass biste() nur eine Methode im Objekt "Jemand" ist (er gibt ihr den korrekten Kontext "this" mit), folgerichtig sollte er doch auch beim Aufruf der inneren Funktion meinName() den entsprechenden Kontext mitliefern.

                                Wäre es eine globale, dann könnte man sie auch von außerhalb des Objekts "Jemand" oder von außerhalb der Funktion "biste()" aufrufen, was natürlich nicht möglich ist.

                                Du musst natürlich die globale Variabel meinName erst setzen bevor du sie vewrwenden kannst.

                                Das verstehe ich nicht: Die Funktion ist doch definiert, und du hälst sie für global, weil kein var davor steht. Also müsste sie von außen aufrufbar sein. Wieso sollte man dann zusätzlich nochmal "die globale Variabel meinName erst setzen" müssen? Das ergibt für mich keinen Sinn...

                                Don P

                                1. Groß? Wieso das denn? Es gibt keinen Unterschied. Gar keinen. Folgende Statements bewirken immer genau das gleiche:

                                  function f() {...};
                                  f = function() {...};
                                  var f = function() {...};

                                  nein, tun sie nicht.
                                  Der Punkt ist, f wird erst zur Laufzeit erzeugt, d.h. du musst die äüßere Funktion zuerst aufrufen, damit die inneren Variabeln einen Wert haben, werden diese nicht mit var lokal gemacht sind stehen diese im globalen Kontext zu Verfügung.

                                  Im globalen Kontext ist es ebenfalls eine *private* Funktion, aber diesmal des globalen Objekts, was sie erst zur globalen Funktion macht.

                                  Das mag richtig sein, nur du kannst in diesem Fall ausserhalb der Funktion auf diese Variabel zughreifen mit var nicht.

                                  Bei gewöhnlichen Variablen gibt es bekanntlich einen Unterschied zwischen z.B. "v=1;" und "var v=1;". Im ersten Fall wird immer eine globale Variable angelegt, im zweiten Fall immer eine private Variable im aktuellen Kontext.

                                  Dass es aber eine Funktion des globalen Objekts ist, stimmt definitiv nicht! Es ist hier eine "innere" Funktion von biste().

                                  und sobald du biste() augeferufen hast ist es eine globale Funktion.

                                  Natürlich, weil sie vorher gar nicht existiert. Deine Aussage stimmt insofern, dass die innere Funktion auf die inneren Variabeln zugreifen kann, also soetwas wie eine privilegierte Funktion ist. Aber es ist halt eine normale globale Variabel die auf die lokalen zugreifen kann:

                                  function Obj() {  
                                  var x = 1;  
                                   closure = function() {  
                                      alert(x);  
                                   }  
                                  }  
                                  Obj();  
                                  x = 2;  
                                  closure();  
                                  
                                  

                                  Ähhäm... jetzt dämmert mir langsam was du meinst:
                                  Weil man innere Funktionen nicht explizit mit "var" privatisieren kann (die Privatisierung geschieht ja automatisch, siehe oben), glaubt biste() immer, bei der inneren Funktion handele es sich um eine globale, und jubelt ihr deshalb das globale Objekt als "this" unter.

                                  Ja, der Punkt dabei ist, dass das aber auch mit var geschieht.

                                  Das wäre logisch, aber ich halte es trotzdem für einen Fehler in der Konzeption. Der Compiler erkennt ja, dass biste() nur eine Methode im Objekt "Jemand" ist (er gibt ihr den korrekten Kontext "this" mit), folgerichtig sollte er doch auch beim Aufruf der inneren Funktion meinName() den entsprechenden Kontext mitliefern.

                                  Ich nehme an, dass JS nicht das Konzept - ich bin in einer Funktion also in einem Objekt - kennt, sondern der Kontext sich aus dem aufrufendem Objekt ergibt.

                                  window.f() { this = window}
                                  obj.f() { this = obj}
                                  obj.obj2.f() { this = obj.obj2;}

                                  und bei einer inneren lokal definierten Funktion ist der Kontext null also wird laut ECMA Spezifikation this = window

                                  Wäre es eine globale, dann könnte man sie auch von außerhalb des Objekts "Jemand" oder von außerhalb der Funktion "biste()" aufrufen, was natürlich nicht möglich ist.

                                  wieso nicht? wenn der Varibale ein Wert zugewiesen wurde, kann man das.

                                  Du musst natürlich die globale Variabel meinName erst setzen bevor du sie vewrwenden kannst.

                                  Das verstehe ich nicht: Die Funktion ist doch definiert, und du hälst sie für global, weil kein var davor steht. Also müsste sie von außen aufrufbar sein. Wieso sollte man dann zusätzlich nochmal "die globale Variabel meinName erst setzen" müssen? Das ergibt für mich keinen Sinn...

                                  Weil sie erst zur Laufzeit gesetzt wird.

                                  Struppi.

                                  1. Hi Struppi,

                                    Der Punkt ist, f wird erst zur Laufzeit erzeugt, d.h. du musst die äußere Funktion zuerst aufrufen, damit die inneren Variabeln einen Wert haben, werden diese nicht mit var lokal gemacht sind stehen diese im globalen Kontext zu Verfügung.

                                    Ah ja, das stimmt. Hatte erst geglaubt, dass f=function(){...} und var f=function(){...} dasselbe ist. Aber klar, es gibt einen großen Unterschied.

                                    Ich nehme an, dass JS nicht das Konzept - ich bin in einer Funktion also in einem Objekt - kennt, sondern der Kontext sich aus dem aufrufenden Objekt ergibt.

                                    window.f() { this = window}
                                    obj.f() { this = obj}
                                    obj.obj2.f() { this = obj.obj2;}

                                    und bei einer inneren lokal definierten Funktion ist der Kontext null also wird laut ECMA Spezifikation this = window

                                    Da hast du es auf den Punkt gebracht: Dass "der Kontext sich aus dem aufrufenden Objekt ergibt". Das steht ja auch so in der Spezifikation.
                                    Aber eben, dass "bei einer inneren lokal definierten Funktion ist der Kontext null" sein muss, will mir einfach nicht einleuchten, und da bin ich wie gesagt nicht alleine.

                                    Ich kann es zur Kenntnis nehmen, ja, kann auch die damit verbundene Unbequemlichkeit in Kauf nehmen, aber es fehlt mir bis dato das Verständnis, waum es so implementiert ist und nicht vielmehr so, wie man es erwarten würde: Dass nämlich die innere, mit var deklarierte Closure den Kontext des umgebenden, also des aufrufenden Objekts bekommt, wie das sonst auch der Fall ist.

                                    function Obj() {

                                    var closure = function() {
                                      alert(this===window); //gibt 'true' aus
                                     }
                                     closure();
                                    }
                                    Obj();

                                    Laufzeit hin oder her – Der Compiler sollte die mit var deklarierte closure genauso behandeln können, als wäre sie mit this.closure deklariert, was die Übergabe des Kontekxts betrifft, denn er sieht ja, dass es eine innere, lokale Funktion ist, die auch nur von innen aufgerufen werden kann.

                                    Wenn sie nicht mit var deklariert wird, ist sie nach dem ersten Aufruf global, das stimmt. Dann darf sie von mir aus auch den globalen Kontext haben, ich wil ja nicht so sein ;)

                                    Gruß, Don P