2011-01-03 3 views
1

Я пишу плагин для jQuery, и у меня есть беспорядок в голове с проблемой контекста в javascript.jQuery плагин, контекст и setTimeout

Это упрощенная версия моего плагина:

(function($){ 

$.fn.myplugin = function(options){ 
    return new MyPlugin(this, options); 
}; 


function MyPlugin(el, o) 
{ 
    this.root = el; 
    this.input_box = el.find('#the_input'); 
    this.map = null; 
    this.timeout = null; 
    var self = this; 

    self.input_box.keyup(function(){ 
    if(self.timeout!==null) 
    { 
     clearTimeout(self.timeout); 
    } 
    self.timeout = setTimeout(function(){ 
      self.search_address(self); 
      }, 500); 
    }); 
} 

MyPlugin.prototype = { 

    search_address : function(context){ 
      geocoder.geocode({'address':$('#direction').val()}, 
      function(results, status){ 
       var lat = results[0].geometry.location.lat(); 
       var lng = results[0].geometry.location.lng(); 
       var latlng = new google.maps.LatLng(lat, lng); 

       context.select_address(latlng, '');         
    }, 

    select_address : function(latlng, text){ 
     self.root.find('#url').val('http://maps.google.com/?q='+encodeURI($('#direccion').val())+'&ll='+coords.lat()+','+coords.lng()+'&ie=UTF8&oe=UTF8&z=18'); 
    } 
}; 
})(jQuery); 

Я читал, что SetTimeout устанавливает контекст глобального объекта, так что я сделал замыкание, чтобы иметь возможность передать контекст search_address функции. Это позволило мне вызвать select_address из функции обратного вызова в функции geocode, но этот обратный вызов вызывает select_address, и там контекст снова нежелателен: self.root не найден.

Я укомплектовать потерял, как обрабатывать контекст, я хоть что использование var self=this при инициализации «объекта» Я хотел бы избежать этих проблем ...

я должен отметить, что select_address можно назвать непосредственно ...

ответ

1

Использование this в этой точке, чтобы обратиться к текущему контексту:

select_address : function(latlng, text){ 
    this.root.find('#url').val('http://maps.google.com/?q='+encodeURI($('#direccion').val())+'&ll='+coords.lat()+','+coords.lng()+'&ie=UTF8&oe=UTF8&z=18'); 
} 
+0

Почему само не работает там? Имейте в виду, что select_address может быть вызван напрямую ... Я хотел бы знать правило, чтобы справиться с этим и избежать проб и ошибок. –

+0

'self' - это переменная, которую вы имеете, но она отсутствует в текущей области. Если вам нужен текущий контекст, вы можете использовать 'this', вы просто используете контрольный держатель, например' self', когда 'this' может измениться, например, в обратном вызове, который вы не контролируете. –

+0

Итак, я должен создать «self» var в любом месте, которое может измениться в контексте, и не может полагаться на self, созданное в инициализаторе ... Итак, хорошая практика - передать контекст обратным вызовам? –

1

Я только что узнал что-то прохладное, который фиксирует контекст SetTimeout в JQuery 1.4+.

Вы можете использовать jQuery.proxy для решения проблемы контекста.

Вот мой код:

 

    Application = function() 
    { 
     this.AMethod = function(){}; 

     setTimeout($.proxy(this.AMethod,this), 100); 


    } 

После тайм-аута, то Application.AMethod выполняется, и, таким образом, «Application» контекст сохраняется

LE: Alternativelly вы можете создать свою собственную функцию прокси очень просто, если вы не хотите, чтобы ваш плагин ограничивался только jQuery 1.4+:

 

    function proxy(func, context) 
    { 
     return function(){ return func.apply(context, arguments);} 
    }