Проблема с 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 и аргументы были бы "на месте". |
Кстати, извините за плохое форматирование кода, что-то никак не получилось выравнять.
|
|
Хм. Я это читал и примерно понимаю как работает this.
Я и привел разные способы, в том числе с явным вызовом call(this) нужного объекта. Но тогда теряются аргументы. Тут же гуглевская функция, была бы моя - проблем бы не было. Сейчас, конечно, еще раз внимательно перечитаю статью, но думаю, так и не найду ответа. |
Раз 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)); |
Спасибо, работает.
Еще хотел поинтересоваться, а такое добавление нового метода bind может как-нибудь сказать на использовании различных библиотек: jquery, prototype и т.п? В этих же библиотеках тоже используется bind - это никак мешать не будет? Я просто взглянув на ваш пример, вспомнил, что можно же было просто сохранить ссылку на this в переменной, ну типа сделать так: var that = this; GDownloadUrl("data.xml", function(data, responseCode) { that.parseXML(data, responseCode) }); Но ваш способ мне больше нравится, только вот не знаю, нет ли в нем подводных камней? Вы бы какой способ порекомендавали, через bind или как я чуть выше написал? |
Если у вас Prototype, то там этот метод уже определен, просто чуть сложнее, но использование в вашем случае такое же. JQuery вроде не пишет ничего в прототипы. Остальные не знаю, надо смотреть мануалы/код.
|
Часовой пояс GMT +3, время: 13:05. |