2010-07-20 3 views
1

Я новый прототип языков на основе и прочитал этот вопрос:Javascript прототип связывают

Preserving a reference to "this" in JavaScript prototype functions

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

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

спасибо.

Edit:

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

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){ ... } 

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

+0

Я не думаю, что вы имеете в виду «прототипную подпись» - вы говорите о собственности прототипа, не так ли? – Skilldrick

+0

Под «сигнатурой прототипа» я имею в виду определение такого метода: myObj.prototype.myFunction = function() {...} –

ответ

1

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

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

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

Для получения дополнительной информации см. Вторую часть this answer.

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

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

Спасибо за отзыв CMS. Кажется, у вас есть глубокое знание темы, и я бы хотел опубликовать немного больше кода, показывая вам то, что я пытаюсь выполнить. Я отправлю ему ответ ниже, чтобы он был более читабельным. –

+0

@ Андрей, я видел ваш код, посмотрю на мой ответ. – CMS

+0

Я согласен. См. Мой ответ ниже. –

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

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

Если вы хотите узнать, лучшие практик в области объектов JavaScript и прототипном наследовании, смотреть Douglas Crockford's videos.

+0

Спасибо Skilldrick, я обязательно просмотрю эти видео. –

0

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

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

+0

Это связано с тем, как вызывается метод, поскольку вы передаете только ссылку на него, библиотека Ajax будет вызывать обычно аргумент без информации о базовом объекте, например: 'var t = new Test(), m = t .nextCallback; m(); 'В предыдущем примере' m' ссылается на метод, как если бы вы передали его как аргумент, вызывая 'm();' будет устанавливать значение this this для глобального объекта. – CMS

Смежные вопросы