2017-07-07 6 views
1

Wenn ich app.update() in Konsole aufrufen funktioniert dies, aber wenn ich requestAnimationFrame verwenden es einen Fehler:Passing Klasse Methode in request

Uncaught TypeError: Cannot read property 'drops' of undefined at update (oee.html:40)

Es funktioniert während setInterval verwenden.

Was fehlt mir?

<!DOCTYPE html> 
<html> 
    <head> 
    <meta charset="utf-8"> 
    <title></title> 
    <style media="screen"> 
     *{ 
     margin:0; 
     padding:0; 
     } 
     #app{ 
     height:100vh; 
     width:100vw; 
     background-color: red; 
     overflow: hidden; 
     } 
     .drop{ 
     position:absolute; 
     background-color:#fff; 
     top:10px; 
     width: 5px; 
     } 
    </style> 
    </head> 
    <body> 
    <div id="app"> 
    </div> 
    <script type="text/javascript"> 
     class App{ 
     constructor(){ 
      this.el = document.getElementById("app"); 
      this.height=this.el.clientHeight; 
      this.width=this.el.clientWidth; 
      this.drops=[]; 
      for(var i=0;i<100;i++){ 
      this.drops.push(new Drop(this.height,this.width)); 
      } 
     } 
     update(){ 
      this.drops.forEach(function(drop){ 
      drop.update(); 
      }); 
     } 
     } 

     class Drop{ 
     constructor(appHeight,appWidth){ 
      this.speed=Math.random(); 
      this.el=document.createElement("div"); 
      this.el.setAttribute("class","drop"); 
      this.el.style.height=(Math.random()*10+5)+"px"; 
      this.el.style.left=(Math.random()*appWidth)+"px"; 
      this.appHeight=appHeight; 
      document.getElementById("app").appendChild(this.el); 
      this.el.style.top=0; 
     } 

     update(){ 
      this.top=this.el.style.top.replace("px",""); 
      this.el.style.top=(this.top>this.appHeight)?"0px":(parseFloat(this.top) + parseFloat(this.speed*300))+"px"; 
     } 
     } 
     var app=new App(); 
     requestAnimationFrame(app.update); 
    </script> 
    </body> 
</html> 
+0

Mögliches Duplikat von [requestAnimationFrame mit diesem Schlüsselwort] (https://stackoverflow.com/questions/6065169/requestanimationframe-with-this-keyword) | 'this 'ändert sich bei der Verwendung von requestAnimationFrame, so dass Sie' .bind() 'die Funktion wie folgt verwenden müssen: https://codepen.io/anon/pen/QgVxxK – yuriy636

Antwort

1

Wenn Sie app.update() rufen, rufen Sie die update Funktion als Methode des app Objekts.

Aber der Code in der Frage stellen sich gezeigt, nicht Ihre Funktion als Methode:

requestAnimationFrame(app.update); 

Wenn Sie app.update schreiben (ohne Klammern zu verwenden), sind Sie nur einen Verweis auf die app.update Funktion bekommen als eine eigenständige Funktion. Es verliert die Verbindung zum Objekt app. Wenn requestAnimationFrame() später Ihre update Funktion aufruft, ruft es die Funktion direkt ohne this Objekt auf. Also, wenn update Referenzen this.drops es fehlschlägt.

Sie haben keine Liste Ihrer setInterval() Version, aber eine Sache können wir sicher sein, dass es tat nicht sieht wie folgt aus:

setInterval(app.update, 10); 

Wenn das der Code waren Sie verwendet wird, müsste es das gleiche Problem, das Sie mit requestAnimationFrame() haben. Sie haben vielleicht so etwas wie folgt geschrieben:

setInterval(function() { 
    app.update(); 
}, 10); 

Jetzt ist Ihre setInterval() Rückruf die anonyme Funktion ist, und dass Funktionsaufrufe app.update()als Methode.

Sie können dasselbe mit requestAnimationFrame() tun, außer dass Sie jedes Mal, wenn Sie auf einen anderen Frame warten möchten, requestAnimationFrame() anrufen müssen. Mit anderen Worten, es ist eher setTimeout() als setInterval(). So könnte es so aussehen:

var updater = function() { 
    app.update(); 
    requestAnimationFrame(updater); // for subsequent frames 
}; 

requestAnimationFrame(updater); // for the first frame 

Jetzt sollte Ihr Code wie erwartet funktionieren.

Hier ist ein updated version of yuriy636's CodePen test mit Animation funktioniert.

Verwandte Themen