почему «this» является объектом DOMWindow при выполнении обратного вызова службы маршрутов Google maps

#javascript #google-maps #this

#javascript #google-карты #это

Вопрос:

итак, у меня есть объект, определенный следующим образом (упрощенный):

 mapRoute : {
            isInit : false,
            latLang : "",
            directionsService :  null,
            directionsRenderer : null,

            init : function() {
                if(!this.isInit) {
                    this.directionsService = new google.maps.DirectionsService();
                    this.directionsRenderer = new google.maps.DirectionsRenderer();
                    this.directionsRenderer.setPanel(document.getElementById("google_route_results"));
                    this.isInit = true;
                }
            },  


            planRoute : function() {
                var from;
                var to;

                from = $('#addressFrom').val();
                to = this.LatLang;

                var directionsRequest = {
                    origin:from,
                    destination:to,
                    travelMode: google.maps.DirectionsTravelMode.DRIVING
                };

                this.directionsService.route(directionsRequest, this.planRouteCallback);
            },

            planRouteCallback : function(result,status){
                if(status == google.maps.DirectionsStatus.OK) {
                    this.directionsRenderer.setDirections(result);
                    this.directionsRenderer.setMap(google_map_object);
                } else {
                    this.handleErrors(status);
                }
            },

            //handleErrors
            handleErrors : function(statusCode) {
                //do stuff
            },


        }//end mapRoute
  

однако, когда выполняется мой planRouteCallback, я получаю ошибки, потому что «это» относится к объекту DOMWindow, а не к моему объекту MapRoute. почему это так, и могу ли я что-нибудь с этим сделать?

Ответ №1:

Проблема в том, что функция выполняется не из контекста mapRoute объекта. Так, например:

 var foo = {bar: 10, fn: function(){ alert(this.bar); }};
foo.fn(); // called within the context of the object foo, so it alerts 10

var noContextFn = foo.fn;
noContextFn(); // uh oh, no context, alerts undefined
  

Когда вы передаете свой обратный вызов mapRoute.planRouteCallback другим функциям, они теперь имеют ссылку на нужные функции, но не будут выполнять этот обратный вызов в контексте mapRoute , как указано выше.

Вы могли бы создать анонимную функцию и использовать шаблон self = this каждый раз, когда вы передаете обратные вызовы в качестве параметров, хотя вам, вероятно, лучше исправить саму функцию раз и навсегда. Вы можете привязать функцию. После того, как mapRoute объект был создан, вы можете запустить:

mapRoute.planRouteCallback = mapRoute.planRouteCallback.bind(mapRoute);

(Обратите внимание, bind() может быть реализовано не во всех браузерах, смотрите MDC для реализации, которую вы можете использовать).

Ответ №2:

Во-первых, «this» в javascript немного сложно и зависит от того, где была вызвана функция, а не только от того, где она была определена.

Самое быстрое кроссбраузерное решение — использовать замыкание. У Google на самом деле есть отличная статья о закрытии с помощью Google Maps здесь.

http://code.google.com/intl/en/apis/maps/documentation/javascript/v2/events.html#Event_Closures

У вас есть доступ к методу GEvent.bind, который вы могли бы использовать для правильной ссылки на свой обратный вызов.

  GEvent.bind(map, "click", myCounter, myCounter.increment);
  

Но я не знаю, как реализовать это с помощью direction route. Кроме того, это может быть устаревшим с версией v2. Вот лучшая ссылка на maps v3

http://code.google.com/intl/en/apis/maps/documentation/javascript/events.html

Итак, возможно, рассмотрим что-то вроде этого:

  var directionsRequest = {
                origin:from,
                destination:to,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            };

 var that = this;
 var planRouteCallback = function(result,status){
            if(status == google.maps.DirectionsStatus.OK) {
                that.directionsRenderer.setDirections(result);
                that.directionsRenderer.setMap(google_map_object);
            } else {
                that.handleErrors(status);
            }
        },

 this.directionsService.route(directionsRequest, planRouteCallback);
  

Простые замыкания действительно помогают с обратными вызовами.

Ответ №3:

В итоге я использовал прокси-сервер jQuery для получения желаемых результатов

 this.directionsService.route(directionsRequest, $.proxy( this.planRouteCallback,this));