XMLHttpRequest внутри объекта: как сохранить ссылку на «это» - PullRequest
8 голосов
/ 11 мая 2010

Я делаю несколько Ajax-вызовов изнутри объекта javascript .:

myObject.prototye = {
  ajax: function() {
    this.foo = 1;

    var req = new XMLHttpRequest();
    req.open('GET', url, true);
    req.onreadystatechange = function (aEvt) {  
      if (req.readyState == 4) {  
        if(req.status == 200)  {
          alert(this.foo); // reference to this is lost
        }
      }
  }
};

Внутри функции onreadystatechange это больше не относится к основному объекту, поэтому у меня нет доступа к this.foo. Как я могу сохранить ссылку на главный объект внутри событий XMLHttpRequest?

Ответы [ 2 ]

7 голосов
/ 11 мая 2010

Самый простой подход обычно заключается в сохранении значения this в локальной переменной:

myObject.prototype = {
  ajax: function (url) { // (url argument missing ?)
    var instance = this; // <-- store reference to the `this` value
    this.foo = 1;

    var req = new XMLHttpRequest();
    req.open('GET', url, true);
    req.onreadystatechange = function (aEvt) {  
      if (req.readyState == 4) {  
        if (req.status == 200)  {
          alert(instance.foo); // <-- use the reference
        }
      }
    };
  }
};

Я также подозреваю, что ваш myObject идентификатор действительно является функцией конструктора (вы присваиваете prototype свойство).

Если это так, не забудьте включить правильное свойство constructor (поскольку вы заменяете весь prototype), которое просто является ссылкой на конструктор.

Возможно, не по теме, но рекомендуется прочитать:

5 голосов
/ 11 мая 2010

Другое простое решение - привязать к нему вашу функцию onreadystatechange. bind -ing функция делает по существу то же самое, что и в ответе CMS (то есть добавляет значение к закрытию), но bind делает это прозрачным образом: вы продолжаете использовать this вместо установки instance переменная.

Вот реализация Function#bind, если в вашей кодовой базе ее нет:

Function.prototype.bind = function(obj) {
    var __method = this;
    var args = []; for(var i=1; i<arguments.length; i++) args.push(arguments[i]);
    return function() {
        var args2 = []; for(var i=0; i<arguments.length; i++) args2.push(arguments[i]);
        return __method.apply(obj, args.concat(args2));
    };
}

А вот как вы можете использовать его в своем коде:

myObject.prototype = {
  ajax: function() {
    this.foo = 1;

    var req = new XMLHttpRequest();
    req.open('GET', url, true);
    req.onreadystatechange = function (aEvt) {  
      if (req.readyState == 4) {  
        if(req.status == 200)  {
          alert(this.foo); // reference to this is *kept*
        }
      }
    }.bind(this) // <- only change
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...