Don P: Fehlermeldung, aber warum?

Hallo,

Der Browser meldet bereits in der ersten Zeile meines Scripts "Fehler: requestAnimationFrame is not defined" und bricht ab.

if(!requestAnimationFrame) {  
  
  requestAnimationFrame =  
    mozRequestAnimationFrame || webkitRequestAnimationFrame ||  
    oRequestAnimationFrame   || msRequestAnimationFrame ||  
    function(callback, element){setTimeout(callback, 1000 / 60);};  
}  

Gerade weil es vielleicht nicht definiert ist, will ich das ja erst mal mit if abfragen und die Zuweisung ggf vornehmen.

Die Abfrage mit if(!window.requestAnimationFrame) { /*...*/ } funktioniert zwar, aber die Zuweisung nachher trotzdem nicht. Auch da muss man jeweils window. davorsetzen, damit es klappt.

Stehe ich jetzt völlig auf dem Schlauch oder was ist da los? Seit wann kann man denn nicht mehr einfach die Existenz mit if abfragen?
Weil ich praktisch nie mit globalen Variablen arbeite, ist mir da vielleicht etwas engangen?

Gruß, Don P

  1. [latex]Mae  govannen![/latex]

    Der Browser meldet bereits in der ersten Zeile meines Scripts "Fehler: requestAnimationFrame is not defined" und bricht ab.

    Jepp.

    Weil ich praktisch nie mit globalen Variablen arbeite, ist mir da vielleicht etwas engangen?

    Der typeof-Operator vermutlich.

    Stur lächeln und winken, Männer!
    Kai

    --
    Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
    in Richtung "Mess up the Web".(suit)
    SelfHTML-Forum-Stylesheet
    1. [latex]Mae  govannen![/latex]

      Der typeof-Operator vermutlich.

      Möglichkeit 2: Die Variabkle deklariern (sollte man ohnehin _immer_ tun)

      var requestAnimationFrame;  
        
      if(!requestAnimationFrame) {  
         // machwas  
      }
      

      Stur lächeln und winken, Männer!
      Kai

      --
      Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
      in Richtung "Mess up the Web".(suit)
      SelfHTML-Forum-Stylesheet
      1. Möglichkeit 2: Die Variabkle deklariern (sollte man ohnehin _immer_ tun)

        var requestAnimationFrame;

        if(!requestAnimationFrame) {
           // machwas
        }

          
        In dem spezifischen Fall nicht so sinnvoll, denn requestAnimationFrame ist eine eingebaute Methode:  
        <http://paulirish.com/2011/requestanimationframe-for-smart-animating/>  
        <https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame>  
          
        Mathias
        
  2. if(!requestAnimationFrame) {

    »Prüft, ob eine globale oder lokale Variable nach Boolean umgewandelt true ergibt. Wenn weder eine lokale noch eine globale Variable dieses Namens existiert, bricht das Script hier mit einem Ausnahmefehler (einer sogenannten Exception) ab: ReferenceError: objekt not defined.«
    http://aktuell.de.selfhtml.org/artikel/javascript/objektabfragen/#obj

    requestAnimationFrame =
        mozRequestAnimationFrame || webkitRequestAnimationFrame ||
        oRequestAnimationFrame   || msRequestAnimationFrame ||
        function(callback, element){setTimeout(callback, 1000 / 60);};

    Dasselbe hier. Wenn der Bezeichner mozRequestFrame und keine solche Variable im Funktions- bzw. globalen Scope gefunden wird, dann gibt es einen ReferenceError (vgl. ES5 10.2.1, GetBindingValue).

    Gerade weil es vielleicht nicht definiert ist, will ich das ja erst mal mit if abfragen und die Zuweisung ggf vornehmen.

    Dann verwende window.requestAnimationFrame, typeof requestAnimationFrame != 'undefined' oder == 'function', 'requestAnimationFrame' in window oder eine andere Methode, die keine Exception wirft.

    Die Abfrage mit if(!window.requestAnimationFrame) { /*...*/ } funktioniert zwar

    Na also.

    aber die Zuweisung nachher trotzdem nicht.

    Weil da derselbe Fall vorliegt.

    Auch da muss man jeweils window. davorsetzen, damit es klappt.

    Ja. »Globale Variablen sind in JavaScript nichts anderes als Eigenschaftes des globale Objektes window. Also kann man einfach if (window.globaleVariable) bzw. if (window["globaleVariable"]) notieren. Der Vorteil gegenüber if (globaleVariable) ist, dass das Script nicht mit einem Ausnahmefehler abbricht, wenn selbige Variable nicht existiert.« (a.a.O.)

    Wenn du obj1.obj2 schreibst, so wird erst der Bezeichner obj1 aufgelöst (Identifier Resolution). Dabei kommt eine Referenz heraus. Dann wird der Property Accessor evaluiert. Es wird also eine Referenz auf die Eigenschaft »obj2« zur Basis von obj1 erzeugt. Wenn die Eigenschaft nicht existiert, so ergibt der Ausdruck lediglich undefined (vgl. ES5 8.12.3, [[Get]]). Eine Exception tritt nur auf, wenn obj1 eine nicht auflösbare Referenz ist (vgl. ES5 8.7.1, GetValue).

    Stehe ich jetzt völlig auf dem Schlauch oder was ist da los? Seit wann kann man denn nicht mehr einfach die Existenz mit if abfragen?

    Ähm – das konnte man noch nie.

    Weil ich praktisch nie mit globalen Variablen arbeite, ist mir da vielleicht etwas engangen?

    Bei lokalen Variablen ist es dasselbe. Wenn du eine nicht deklarierte lokale Variable ansprichst, dann gibt es ebenfalls eine Nullreferenz und einen entsprechenden ReferenceError.

    function f () {  
       if (!husseldiguggeldidu) { alert('boom'); }  
    }  
    f();
    

    Bei deklarierten Variablen (var-Statement oder formale Parameterliste) ist das was anderes. Diese existieren ja im Variablenobjekt bzw. Aktivierungsobjekt, haben aber zumindest den Wert undefined.

    Mathias

    P.S. Die Überarbeitung des Artikels ist gerade in der Veröffentlichung, die SELFHTML-Redaktion lässt auf sich warten. ;) Bei Interesse kann ich sie dir auch vorab mailen.

    1. Moin!

      P.S. Die Überarbeitung des Artikels ist gerade in der Veröffentlichung, die SELFHTML-Redaktion lässt auf sich warten. ;) Bei Interesse kann ich sie dir auch vorab mailen.

      Nee, jetzt nicht mehr. Du wolltest auf http://aktuell.de.selfhtml.org/artikel/javascript/objektabfragen/#obj-eig verlinken. Aber im Grund ist der gesamte Artikel interessant als Hintergrundinfo zu lesen und für jedermann empfehlenswert.

      - Sven Rautenberg

    2. Hallo,

      if(!requestAnimationFrame) {

      »Prüft, ob eine globale oder lokale Variable nach Boolean umgewandelt true ergibt. Wenn weder eine lokale noch eine globale Variable dieses Namens existiert, bricht das Script hier mit einem Ausnahmefehler (einer sogenannten Exception) ab: ReferenceError: objekt not defined.«
      http://aktuell.de.selfhtml.org/artikel/javascript/objektabfragen/#obj

      Sachen gibt's... da progammiert man abertausende Zeilen Javascript, wähnt ich schon als Könner, und stoplert dann über sowas...

      Dachte, dass eine nicht existierende Variable v bei der Umwandlung zu boolean !v einfach !window.v bzw. !undefined und somit true ergibt statt einer Exception.

      Aber ok, jetzt ist es klar: Es wird also dann nicht automatisch das globale Objekt (window) als Container angenommmen und !window.v ausgewertet. So wäre es wäre doch eigentlich logisch.

      P.S. Die Überarbeitung des Artikels ist gerade in der Veröffentlichung, die SELFHTML-Redaktion lässt auf sich warten. ;) Bei Interesse kann ich sie dir auch vorab mailen.

      Ist ja jetzt ok, danke. Das kann man anscheinend nicht oft genug lesen und verinnerlichen :)

      Gruß, Don P

      1. Aber ok, jetzt ist es klar: Es wird also dann nicht automatisch das globale Objekt (window) als Container angenommmen und !window.v ausgewertet. So wäre es wäre doch eigentlich logisch.

        Jein. In beiden Fällen wird die Variable letztlich am globalen Objekt gesucht. Der Unterschied lässt sich so erklären:

        In beiden Fällen werden Referenzen erzeugt. Eine Referenz besteht vereinfacht gesagt aus einer Basis und einem Namen. Die Basis ist das »Objekt«, an dem nach dem Namen gesucht wird. Die Basis kann entweder direkt ein normales, der Programmierung zugängliches Objekt sein oder ein internes Objekt, der Environment Record eines Ausführungskontexts. Das kann man verallgemeinernd als Variablenobjekt bezeichnen.

        Bei if (foo) ist der globale Ausführungskontext die Basis der Referenz. Letztlich wird wie gesagt am window-Objekt nach der Variable gesucht, denn das ist das Variablenobjekt für den obersten Kontext.

        Bei if (window.foo) hingegen wird explizit das globale Objekt als Referenzbasis verwendet.

        Das führt dann zu einer unterschiedlichen Verarbeitung der Referenzen. Die besagte interne GetValue-Funktion regelt das Auflösen von Referenzen:

        »4. If IsPropertyReference(V), then
        a) If HasPrimitiveBase(V) is false, then let get be the [[Get]] internal method of base, otherwise let get be the special [[Get]] internal method defined below.
        b) Return the result of calling the get internal method using base as its this value, and passing GetReferencedName(V) for the argument.«

        Wenn die Basis ein normales Object ist (oder ein Primitive, der dann vorher in ein Object umgewandelt wird), dann rufe dessen [[Get]]-Methode auf. Die gibt bei unbekannten Eigenschaften wie gesagt einfach undefined zurück.

        »5. Else, base must be an environment record.
        Return the result of calling the GetBindingValue (see 10.2.1) concrete method of base passing GetReferencedName(V) and IsStrictReference(V) as arguments.«

        Wenn die Basis ein »Object Environment Record« ist – das ist der Fall, wenn Identifier im globalen Kontext aufgelöst werden –, so rufe GetBindingValue auf. Diese Methode ist nun pingelig; wenn kein entsprechendes Binding existiert, dann quittiert sie mit einem ReferenceError.

        Mathias