Javascript прототип привязки - PullRequest
1 голос
/ 21 июля 2010

Я новичок в основанных на прототипах языках и прочитал этот вопрос:

Сохранение ссылки на "this" в функциях прототипов JavaScript

Мне интереснокакое значение имеет использование подписи на основе прототипа для присоединения методов к объекту.Почему бы просто не присоединить метод к свойству объекта в определении объекта?

Во-вторых, при использовании подписи прототипа для определения методов объекта, почему указатель «this» разрешает объект окна внутри объектафункционировать?Это кажется недостатком дизайна.Если это не так, может кто-то объяснить или указать мне объяснение, почему нет?

Спасибо.

Редактировать:

Этот код работает должным образом, отображая окно сообщения со словом «здесь» внутри.

function Obj()
{   
    this.theVar = 'here';
    this.method2 = function(){ alert( this.theVar ); }
}

Obj.prototype.method3 = function(){ this.method2(); }
Obj.prototype.method4 = function(){ this.method3(); }

var obj = new Obj();
obj.method4();

Этот код является моим обратным вызовом AJAX, и указатель 'this' ссылается на объект 'window' во время выполнения.

Test.prototype.nextCallback = function( response )
{
    if( response.Status != 'SUCCESS' )
        show_message( response.Message, false );
    else
        this.setQuestion( response.Question );
}

Test.prototype.setQuestion = function( question ){ ... }

Указатель 'this' на самом деле работает правильно до вызова AJAX, но не после.Это результат того, что контекст nextCallback () не восстанавливается должным образом после возврата вызова AJAX и до вызова обратного вызова?Есть ли способ исправить это?

Ответы [ 3 ]

1 голос
/ 21 июля 2010

1 - точка добавления членов в прототип конструктора - это повторное использование поведения.

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

2- Это происходит потому, что каждая функция имеет свой собственный контекст выполнения (там хранится значение this)и значение this устанавливается неявно, когда вы вызываете функцию, а если ссылка на функцию не имеет базового объекта (например, foo();, vs obj.foo()), глобальный объект будет установлен какthis значение внутри вызванного метода.

Подробнее см. Вторую часть этого ответа .

Редактировать: После просмотра кодаКажется, вы передаете ссылку на метод nextCallback как функцию обратного вызова некоторого события успеха Ajax, если это так, базовый объект ссылки будет потерян, общий подход, который может заключаться в использовании анонииФункция mous, которая корректно вызывает ваш метод, например:

var obj = new Test();
//...
someAjaxLib(url, function (data) {
  obj.nextCallback(data); // `this` will refer to obj within nextCallback
});

Другим подходом может быть привязка метода к его экземпляру в конструкторе, имейте в виду, что метод будет определен как собственное свойство в каждый экземпляр объекта , который вы создаете, не будет наследоваться, например:

function Test() {
  var instance = this; // store reference to the current instance

  this.nextCallback = function( response ) {
    if( response.Status != 'SUCCESS' ) {
      show_message( response.Message, false );
    } else {
      instance.setQuestion( response.Question ); // use the stored reference
    }
  }
}
0 голосов
/ 21 июля 2010

В моем случае кажется, что, когда метод добавляется к объекту через сигнатуру прототипа и впоследствии передается для использования в качестве метода обратного вызова AJAX, этот метод затем переопределяется в глобальный объект (окно) и теряет егооригинальный контекст.То есть метод больше не является членом прототипа, для которого он был определен.

Я только протестировал это в Firefox.Я предполагаю, что такое поведение вызвано тем, что вызов AJAX физически выполняется в другом потоке ОС, а по возвращении из вызова AJAX указанный и обратный метод поиска обнаруживается и выполняется.Не делается попытка разрешить исходный контекст метода между потоками.Опять же, это всего лишь предположение.

0 голосов
/ 21 июля 2010
  1. В JavaScript, если вы используете функцию в качестве конструктора для создания новых объектов, то назначение метода для this в конструкторе означает, что каждый новый объект получает новый определенный метод.Присвоение прототипа означает, что вы получаете только одно определение метода в прототипе.

  2. Да, this указание на глобальный объект в некоторых случаях является недостатком проекта, ноЯ не думал, что в случае, если вы упомянули, что это произойдет.

Если вы хотите изучить лучшие практики в объектах JavaScript и наследовании прототипов, посмотрите видео Дугласа Крокфорда .

...