2012-10-31 18 views
5

Zdaję sobie sprawę, że kompilator TypeScript stara się zachować zgodność ze zwykłym starym JavaScriptem, ponieważ TypeScript jest rzeczywiście JavaScript. Istnieje jednak rozdźwięk między tym, co IntelliSense interpretuje jako słowo kluczowe "to", a tym, co faktycznie rozwiązuje w czasie wykonywania. Na przykład, należy rozważyć następujące wywołanie maszynopis 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 
      }); 

     } 

oraz jej odpowiedni 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 
        } 
       } 

Teraz, kiedy najechaniu na linię „var siebie = to” w onGetAgenciesComplete w pliku źródłowym maszynopis, Definicja Intellisense zmiennej "self" wskazuje, że jest ona typu HomePageViewModelBase, gdzie HomePageViewModelBase jest klasą zawierającą powyższe metody.

Wygenerowany Javascript dla wyżej wymienionych jest następujący:

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); 
       } 
      } 
     }; 

które po wykonaniu zmienną „ja” w HomePageViewModelBase.prototype.onGetAgenciesComplete uchwala się, co wygląda jak AjaxContext a nie instancję HomePageViewModelBase. Czy to oczekiwane zachowanie, czy powinienem zgłosić to jako błąd?

Odpowiedz

6

Tak, prawdopodobnie powinieneś zgłosić to jako błąd, ponieważ this w obrębie $.ajax() ma się odnosić do samego obiektu $.ajax().

Jeśli chcesz, aby przejść wokół niego tak, że działa, zmień swoją funkcję sukces:

success: self.onGetAgenciesComplete 

Lub jeśli chceszthis stanąć do swojej klasy, wystarczy użyć kontekstowe metody od $ .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

dobra odpowiedź - ustawienie kontekst działa. Zanim jednak zgłosisz błąd, rozważ to pytanie: W jaki sposób kompilator poprawnie wywnioskuje kontekst "tego", gdy funkcja może być wywołana w wielu różnych kontekstach. Uważam, że pokazuje właściwy kontekst oparty na założeniu, że funkcja jest wywoływana bezpośrednio, a nie w kontekście wywołania zwrotnego z innego źródła. – Fenton

+0

Zgadzam się, a jeśli cokolwiek to jest dobra praktyka (jeśli cokolwiek oprócz czytelności), aby wyjaśnić, jaki powinien być kontekst "tego". Sądzę, że kluczem do sprawy było to, że nie powinien on wiedzieć, że jest to '$ .ajax', ponieważ tak to działa w jQuery? –

+0

@mcpDESIGNS, to jest dobre wytłumaczenie, dziękuję. Nigdy nie wiedziałem o kontekście $ .ajax, który jest jeszcze lepszym rozwiązaniem. Podwójne dzięki.Jesteś także poprawny w punkcie mojego postu, który nie powinien być interpretowany przez intellisense "this" w $ .ajax na instancję bazy HomePageViewModel. –

3

miarę dowolny (w tym Intellisense) analiza statyczna jest zaniepokojony, kontekście onGetAgenciesCompleteja sHomePageViewModelBase i zawsze będzie; z tym wyjątkiem, że w środowisku wykonawczym kontekst zostanie ustawiony dynamicznie, poprzez jawne wewnętrzne powiązanie kontekstu jQuery.ajax. Jedynym sposobem, w jaki Intellisense może określić, że kontekst zmienia się dynamicznie, jest faktyczne wykonanie tej ścieżki kodu, ale nawet to powoduje niejednoznaczność: który kontekst jest właściwym kontekstem?

Co się stanie, jeśli "wypożyczysz" metodę gdzie indziej, na jednorazowe połączenie? Czy Intellisense powinien użyć tej witryny wywołań, aby określić kontekst? Prawdopodobnie nie ...

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

(skrócona dla czytelności).

Powiązane problemy