Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 09.07.2009, 11:27
AntonE
 
Сообщений: n/a

Проблема с this
Добрый день.
В общем, сейчас изучаю GMap API и возникла проблема.
Gmap я указал на всякий случай, знание его необязательно, чтобы помочь мне, главное - это javascript.

Gmap предоставляет метод GDownloadUrl(имя_файла, колбек)
Выглядит это примерно так
GDownloadUrl("data.xml", function(data, responseCode) {
//какой-нибудь код
});

Вот мой код
function Streets() {
      this.map = new GMap2(document.getElementById("map_canvas"));
      this.init();
      // temp - просто переменная для проверки.
      this.temp = 'ok';
      this.load();
    }
    Streets.prototype = {
      init: function() {
        this.map.setCenter(new GLatLng(51.6538, 30.1749), 12);
        this.map.addControl(new GLargeMapControl());
        this.map.addControl(new GMapTypeControl());
      },
      load: function() {
        GDownloadUrl("data.xml", this.parseXML);
      },
      parseXML: function(data, responseCode) {
        // что-нибудь делаем
      }
    };

В моем методе load вызывает гуглевский метод GDownloadUrl, который просто загружает файл data.xml и запускает колбек, которому передает 2 параметра - nodelist и номер статуса.
Я хочу, чтобы колбек вызывал Streets.parseXML и передал ему параметры. Но это у меня пока не получается.
Если я делаю так:
load: function() {
        GDownloadUrl("data.xml", this.parseXML);
      },
      parseXML: function(data, responseCode) {
        alert(this.temp); // undefined, "потеряли" this
        alert(arguments.length); // все хорошо - 2 аргумента.
      }


если так:
load: function() {
        GDownloadUrl("data.xml", this.parseXML.call(this));
      },
      parseXML: function(data, responseCode) {
        alert(this.temp); // результат - ok
        alert(arguments.length); // результат - 0, параметры не передались
      }


если так:
// Так вообще не работает.
      load: function() {
        GDownloadUrl("data.xml", this.parseXML.call(this, data, responseCode));
      },
      parseXML: function(data, responseCode) {
        alert(this.temp);
        alert(arguments.length);
      }


Если так:
load: function() {
        GDownloadUrl("data.xml", this.parseXML.call(this, arguments[0], arguments[1]));
      },
      parseXML: function(data, responseCode) {
        alert(this.temp); // Результат - ок
        alert(arguments.length); // 2 аргумента
        alert(responseCode); // но оба undefined
      }


если так:
load: function() {
        GDownloadUrl("data.xml", function(data, responseCode) {
          // this здесь не указывает на Streets, т.е.
          // вызвать отсюда this.parseXML не получается.
          // Может есть способ?
        });
      },
      parseXML: function(data, responseCode) {
        //...
      }


Подскажите, пожалуйста, как же все-таки вызвать parseXML, чтобы this ссылался на Streets и аргументы были бы "на месте".
Ответить с цитированием
  #2 (permalink)  
Старый 09.07.2009, 11:29
AntonE
 
Сообщений: n/a

Кстати, извините за плохое форматирование кода, что-то никак не получилось выравнять.
Ответить с цитированием
  #3 (permalink)  
Старый 09.07.2009, 11:41
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

http://javascript.ru/tutorial/object/thiskeyword
Ответить с цитированием
  #4 (permalink)  
Старый 09.07.2009, 11:50
AntonE
 
Сообщений: n/a

Хм. Я это читал и примерно понимаю как работает this.
Я и привел разные способы, в том числе с явным вызовом call(this) нужного объекта. Но тогда теряются аргументы.
Тут же гуглевская функция, была бы моя - проблем бы не было.

Сейчас, конечно, еще раз внимательно перечитаю статью, но думаю, так и не найду ответа.
Ответить с цитированием
  #5 (permalink)  
Старый 09.07.2009, 11:58
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Раз GMap не позволяет передавать нужный scope, то лучше определить метод функции bind
Function.prototype.bind = function(scope) {
    var that = this;
    return function() {
        return that.apply(scope, arguments);
    };
};
И тогда
GDownloadUrl("data.xml", this.parseXML.bind(this));
Ответить с цитированием
  #6 (permalink)  
Старый 09.07.2009, 12:27
AntonE
 
Сообщений: n/a

Спасибо, работает.
Еще хотел поинтересоваться, а такое добавление нового метода bind может как-нибудь сказать на использовании различных библиотек: jquery, prototype и т.п?
В этих же библиотеках тоже используется bind - это никак мешать не будет?
Я просто взглянув на ваш пример, вспомнил, что можно же было просто сохранить ссылку на this в переменной, ну типа сделать так:
var that = this;
GDownloadUrl("data.xml", function(data, responseCode) {
  that.parseXML(data, responseCode)
});

Но ваш способ мне больше нравится, только вот не знаю, нет ли в нем подводных камней? Вы бы какой способ порекомендавали, через bind или как я чуть выше написал?
Ответить с цитированием
  #7 (permalink)  
Старый 09.07.2009, 12:38
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Если у вас Prototype, то там этот метод уже определен, просто чуть сложнее, но использование в вашем случае такое же. JQuery вроде не пишет ничего в прототипы. Остальные не знаю, надо смотреть мануалы/код.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
проблема с сабмит mapt Events/DOM/Window 1 15.06.2009 13:45
Проблема спама lliberty AJAX и COMET 1 12.03.2009 16:47
проблема с обработкой DIV nerik AJAX и COMET 2 22.08.2008 17:40
Проблема с маркером kostian02 Общие вопросы Javascript 0 23.06.2008 16:10
проблема с передачей русского текста в Prototype subaru Prototype & script.aculo.us 2 26.07.2007 16:56