2016-03-31 14 views
0

Ich bin auf den Unterschied in diesen Anwendungsfälle verwirrt:Javascript .call() Verwendung. Ein Arbeitsfall, einer nicht. Was ist das Diff?

// CASE 1: Two separate attempts, neither work (see comments) 

    var circle = new google.maps.Circle({ 
      // and then a bunch of properties, all work fine. Including this to show you 
      // where the variable I'm trying to use in call() came from 
    }); 

    circle.initListeners = function(){ 
     this.addListener('mouseover', function(){ 

       // Works if circle is named explicitly in explodeView (see code below), 
       // doesn't work with .call(circle) here, this.setRadius() in explodeView 
       explodeView().call(circle); 

       // Both work fine 
       this.infoWindow.setPosition(this.getBounds().getNorthEast()); 
       this.infoWindow.open(map); 

       // Works with circle.getCenter, not with .call(circle) and this 
       this.timer = setInterval(function(){ 
        map.panTo(this.getCenter()); 
       }, 1000).call(circle) 

       // Works with circle.setRadius, not with this.setRadius 
       function explodeView(){ 
        var radiusExtender = ((300 - tweet.stats.reach) + 1)/60; 
        radiusExtender > 1.15 ? this.setRadius(radiusExtender * radius) : this.setRadius(radius * 1.15); 
       } 
      }); 
     }); 

dies vergleichen mit der folgenden Verwendung von .call(), die ich nach dem Aufstehen einen "this does not have method ._togCircVis(...)" Fehler implementiert, wenn die Funktion ohne .call(map) Aufruf:

// CASE 2: Works 

    // Call to function I added to circle prototype 
    map._togCircVis.call(map) 

    // Successfully receives map and executes correctly 
    google.maps.Map.prototype._togCircVis = function(){ 
     this.circles.forEach(function(circle){ 
     circle.getMap() != null ? circle.setMap(null) : circle.setMap(map); 
     }) 
    }  

Wenn ich den Code in Fall 1 versuche, bekomme ich den gleichen "this does not have method " Fehler, wie ich vor dem Hinzufügen von .call(map) Fall 2 gemacht habe. Gleiche, wenn ich .apply() anstelle von .call() versuchen (ein Hagel Mary Debug-Versuch). Ich verstehe, warum die Hinzufügung zu Fall 2 funktioniert, da es für die aufgerufene Funktion klarstellt, dass ich über das map Objekt spreche, nicht über das Fensterobjekt, wenn ich this für die Variablenzuweisung verwende. Aber warum funktioniert es nicht mit den oben genannten Fällen? MDN-Artikel haben mir geholfen, call (map) zu benutzen, aber haben diesen anderen Gebrauch nicht für mich aufgemacht. Vielen Dank!

+2

'setInterval' Rückkehr keine Funktion, so kann man nicht' es .call'. – zerkms

+0

Super, danke für die Antwort. –

Antwort

3

explodeView().call(circle); Hier rufen Sie normal explodeView (ohne Anruf) und versuchen dann, call auf den Wert aufzurufen (undefined). Stattdessen sollten Sie explodeView.call(circle) schreiben. Sie haben ein sehr ähnliches Problem hier:

setInterval(function(){ 
    map.panTo(this.getCenter()); 
}, 1000).call(circle); 

Sie versuchen call auf einem Objekt aufrufen, die keine Funktion ist. Bevor es undefined war, ist es diesmal eine Nummer (setInterval gibt eine Zahl zurück). Sie könnten bind wie diesen zu erreichen, was Sie wollen:

setInterval(function(){ 
    map.panTo(this.getCenter()); 
}.bind(circle), 1000); 
+1

Oder verwenden Sie einfach 'circle.getCenter', statt' this' und 'bind' unnötig – Bergi

+0

Funktioniert wie ein Charme. Vielen Dank! Ich schätze die Unterscheidung zwischen Fällen. –

+0

@Bergi - Nur sicherstellen, dass ich die Anwendungen von jedem, neu zu Javascript verstehe und versuche, so gründlich wie möglich zu lernen. Trotzdem danke! Ich stimme zu, die Einfachheit ist ein Plus, wird wahrscheinlich sein, was ich behalte –