2012-10-31 19 views
5

Mi rendo conto che il compilatore TypeScript sta tentando di rimanere fedele al semplice JavaScript vecchio, poiché TypeScript è effettivamente JavaScript. Tuttavia, vi è una disconnessione tra ciò che Intellisense interpreta come la parola chiave "this" e ciò che effettivamente risolve durante il runtime. Ad esempio, si consideri la seguente chiamata dattiloscritto ajax:

getAgencies() { 
      var self = this;   
      $.ajax(liveString + "/Home/GetSupportedAgencies", 
      { 
       type: "GET", 
       contentType: "application/json; charset=utf-8", 
       dataType: "json", 
       error: Utilities.Logger.displayAjaxError, 
       success: this.onGetAgenciesComplete 
      }); 

     } 

e il suo corrispondente callback:

onGetAgenciesComplete(agencies) { 
       var self = this; 
        if (agencies == null) 
         Utilities.Logger.displayErrorOnLogConsole("There was an error retrieving supported agencies. Refresh site and try again."); 
        else { 
         $.each(agencies, function (i, a) { 
          self._indexViewModel.agencies.push({ name: a.Name, fullName: a.FullName, shortName: a.ShortName, bbox: a.BBox, countryCode: a.CountryCode }); 
         }); 

         if (Modernizr.geolocation) { 
          navigator.geolocation.getCurrentPosition(
           function (position) { 
            self.initMapPage(position, self); 
           }, 
           function (error) { 
            Utilities.Logger.displayErrorOnLogConsole("Oops, we could not get your location at his time. Please try later."); 
           }); 
         } 
         else { 
          Utilities.Logger.displayErrorOnLogConsole("Sorry, your browser does not return location information."); 
          self.getBusRoutes(self.agencyName); 
         } 


         // end of initialization 
        } 
       } 

Ora, quando mi passa il mouse sopra la linea "var sé = presente" nel onGetAgenciesComplete all'interno del file sorgente dattiloscritto, la definizione Intellisense della variabile "self" indica che è di tipo HomePageViewModelBase, dove HomePageViewModelBase è la classe che contiene i metodi precedenti.

Il Javascript generato per citato è il seguente:

HomePageViewModelBase.prototype.getAgencies = function() { 
      var self = this; 
      $.ajax(liveString + "/Home/GetSupportedAgencies", { 
       type: "GET", 
       contentType: "application/json; charset=utf-8", 
       dataType: "json", 
       error: Utilities.Logger.displayAjaxError, 
       success: this.onGetAgenciesComplete 
      }); 
     }; 
     HomePageViewModelBase.prototype.onGetAgenciesComplete = function (agencies) { 
      var self = this; 
      if(agencies == null) { 
       Utilities.Logger.displayErrorOnLogConsole("There was an error retrieving supported agencies. Refresh site and try again."); 
      } else { 
       $.each(agencies, function (i, a) { 
        self._indexViewModel.agencies.push({ 
         name: a.Name, 
         fullName: a.FullName, 
         shortName: a.ShortName, 
         bbox: a.BBox, 
         countryCode: a.CountryCode 
        }); 
       }); 
       if(Modernizr.geolocation) { 
        navigator.geolocation.getCurrentPosition(function (position) { 
         self.initMapPage(position, self); 
        }, function (error) { 
         Utilities.Logger.displayErrorOnLogConsole("Oops, we could not get your location at his time. Please try later."); 
        }); 
       } else { 
        Utilities.Logger.displayErrorOnLogConsole("Sorry, your browser does not return location information."); 
        self.getBusRoutes(self.agencyName); 
       } 
      } 
     }; 

che, se eseguito "auto" variabile in HomePageViewModelBase.prototype.onGetAgenciesComplete viene risolto in quello che sembra un AjaxContext e non un'istanza di HomePageViewModelBase. È questo comportamento previsto o dovrei segnalarlo come un bug?

risposta

6

Sì, probabilmente si dovrebbe segnalare a loro come un bug, perché il this all'interno di un $.ajax() è destinato a fare riferimento allo stesso oggetto $.ajax().

Se si vuole andare in giro in modo che esso funziona, cambiare la funzione di successo a:

success: self.onGetAgenciesComplete 

O se desidera il this a riposo per la classe, è sufficiente utilizzare il metodo contesto di $ .ajax

$.ajax({ 
    context: this, 
    // now *this* will come from the previous scope, 
    // which in your case, is your class "HomePageViewModelBase" 

    // now that we know for certain what -this- refers to 
    success: this.onGetAgenciesComplete 
}); 
+0

Buona risposta - l'impostazione del contesto funziona. Prima di inviare un bug, considera questa domanda: come può il compilatore inferire correttamente il contesto di 'this' quando la funzione può essere chiamata in molti contesti diversi. Credo che mostri il contesto corretto basato sull'ipotesi che la funzione sia chiamata direttamente, piuttosto che nel contesto di un callback da un'altra parte. – Fenton

+0

Sono d'accordo, e semmai è una buona pratica (se non altro che per la leggibilità) rendere ovvio quale dovrebbe essere il contesto di "questo". Penso che il punto di @ KNji fosse, non dovrebbe sapere che è il '$ .ajax' stesso, dal momento che è così che funziona all'interno di jQuery? –

+0

@mcpDESIGNS, questa è una buona spiegazione, grazie. Non ho mai saputo del contesto $ .ajax che è una soluzione ancora migliore. Doppio grazieHai anche ragione nel punto del mio post che intellisense non avrebbe dovuto riferirsi a "questo" in $ .ajax a un'istanza di HomePageViewModel base. –

3

Per quanto riguarda qualsiasi (compresa Intellisense) l'analisi statica è interessato, il contesto di onGetAgenciesCompletei sHomePageViewModelBase e lo sarà sempre; eccetto che in fase di runtime, il contesto sarà impostato dinamicamente, tramite esplicita associazione interna di contesto jQuery.ajax. L'unico modo in cui Intellisense può determinare che il contesto cambierà dinamicamente è quello di eseguire effettivamente quel percorso di codice, ma anche quello si traduce in ambiguità: quale contesto è il contesto giusto?

E se si "prende in prestito" un metodo altrove, per una chiamata una tantum? Intellisense dovrebbe quindi utilizzare quel sito di chiamata per determinare il contesto? Probabilmente no ...

HomePage.prototype.onGetAgencies.call({ some other context }, ...); 

(accorciata per migliorare la leggibilità.)

Problemi correlati