Дополнение Firefox - `this` работает в одном методе, но не работает в другом методе того же объекта - PullRequest
2 голосов
/ 06 декабря 2010

Я разрабатываю дополнение для Firefox (3.6. *). в следующем коде notify вызывается изнутри init работает нормально, но я получаю сообщение об ошибке this.notify is not a function при вызове из onPageLoad Почему это так?

Также, когда я изменяю вызов на myextobj.notify('title', 'msg'), это работает. То же самое верно для доступа к переменным. Итак, в чем разница между this и именем объекта в качестве префикса?

var myextobj = {
  init: function() {
    this.notify('init', 'We are inside init');
    ...
    var appcontent = document.getElementById("appcontent");   // browser  
    if(appcontent)  
      appcontent.addEventListener("DOMContentLoaded", this.onPageLoad, true);
  },
  onPageLoad: function(aEvent) {
    this.notify('onPageLoad', 'We are inside onPageLoad');
    ...
  },

  notify: function (title, text) {  
    Components.classes['@mozilla.org/alerts-service;1'].  
      getService(Components.interfaces.nsIAlertsService).  
      showAlertNotification(null, title, text, false, '', null);  
  }  
};
window.addEventListener("load", function() { myextobj.init(); }, false);

Ответы [ 3 ]

2 голосов
/ 06 декабря 2010

Когда для события вызывается onPageLoad, 'this' не будет относиться к вашему myextobj.Потому что он не был вызван в контексте вашего объекта myextobj.

То, как я справляюсь с этим, заключается в том, чтобы все функции-члены объекта использовали следующее соглашение.

var myObj = {
   .....
   counter: 0,
   .....
   myFunction: function () {
     var t = myObj;
     t.myOtherFunc();
   },

   ....
   myOtherFunc: function() {
     var t = myObj;
     t.counter++;
   }
};

Посмотрите, как я использую псевдоним myObj как t, чтобы сэкономить на наборе текста и сделать мое намерение использовать this clear.

Теперь вы можете безопасно вызывать свои методы из любого контекста, не беспокоясьо том, на что будет ссылаться this.Если вы действительно не хотите стандартного поведения;в этом случае вы можете посмотреть на методы call и apply.Эта ссылка может помочь: Function.apply и Function.call в JavaScript

2 голосов
/ 06 декабря 2010

Когда вы делаете это:

appcontent.addEventListener("DOMContentLoaded", this.onPageLoad, true);

вы просто добавляете функцию, которая удерживается в onPageLoad в качестве обработчика событий. Соединение с объектом потеряно, и this при выполнении будет ссылаться на глобальный объект.

Просто создайте анонимную функцию, как вы делаете для события load:

var that = this; // capture reference to object
appcontent.addEventListener("DOMContentLoaded", function(event) {
    that.onPageLoad(event);
    // myextobj.onPageLoad(event); should also work in this case
}, true);

Помните, что функции являются объектами первого класса в JavaScript, их можно передавать как любое другое значение. Функции не имеют ссылки на объект, для которого они определены, потому что они не принадлежат этому объекту. Это просто другой тип данных.

То, на какой объект this ссылается в функции, определяется при выполнении и зависит от контекста , в котором выполняется функция. Если вы вызываете obj.func(), тогда контекст равен obj, но если вы назначаете функцию другой переменной раньше, например var a = obj.func (то есть, когда вы добавляете обработчик событий (в некотором смысле)), а затем вызываете a(), this будет ссылаться на глобальный объект (который является window большую часть времени).

0 голосов
/ 14 января 2011

Другой способ добавить прослушиватель событий без потери дорожки this - передать сам this в качестве прослушивателя событий. Однако вы ограничены в том, что функция всегда вызывается handleEvent, поэтому она менее полезна, если у вас много слушателей (если только они не предназначены для разных событий, и в этом случае вы можете включить тип события).

...