4

Я пытаюсь определить базовый класс в JavaScript, который выполняет множество общих функций при создании. Часть этой функции заключается в создании компонента и регистрации обработчиков обратного вызова для этого компонента.Как вы перекрываете привязки к цепочке конструкторов JS?

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

В конкретных терминах у меня есть компонент BasicPage, который создает компонент Table. BasicPage также определяет функцию по умолчанию onRowClick, которая регистрируется в недавно созданном Table.

Теперь я хочу, чтобы создать PageWithSections компонент, который расширяет BasicPage (через call(..) заявление) и подменяет onRowClick. Проблема заключается в регистрации обработчика кликов, когда таблица выполняется внутри конструктора базового класса. Во время этой регистрации onRowClick еще не был переопределен, поэтому ссылка на базовые классы onRowClick.

Я создал jsBin, который иллюстрирует проблему.

http://jsbin.com/uDEjuzeQ/9/edit

Если щелкнуть на каждом поле один раз, в порядке, я хочу дисплей окно сообщения будет:

Нет сообщений; строка нажата; строка нажата; BasicPage onRowClicked; строка нажата; PageWithSections onRowClicked

Что такое правильный способ, чтобы переопределить функцию до конструктора цепи и привязать переопределенную функцию к чему-то в процессе построения базового объекта?

UPDATE Этот вопрос оригинальной ссылка на цепочке прототипов, но на самом деле эти прототипы фактически не используются в этом примере.

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

+2

На самом деле я не вижу наследования в [скрипке, которую вы опубликовали] (http://jsbin.com/uDEjuzeQ/9/edit). Где вас интересует цепочка прототипов? –

+0

Cloudfeet указал на то же самое. Если вы можете предложить лучший заголовок, я его изменю. Я также изменю теги, связанные с этим сообщением. – Snekse

+0

Я внес изменения в исходный вопрос. Я собираюсь оставить это открыто на некоторое время и наградить галочкой, на которую когда-либо отвечают, получает больше всего голосов. – Snekse

ответ

1

Самая большая проблема, которую я вижу, заключается в том, что ваш _onRowClicked (обратный вызов, который вы передаете в таблицу) на самом деле не определен нигде в прототипе.

Вы на самом деле не являетесь , используя прототипическое наследование - вы определяете методы внутри конструктора и вызываете один конструктор из другого.

Попробуйте переформатировать код таким образом, чтобы некоторые из значений по умолчанию для BasicPage были определены в BasicPage.prototype (в настоящее время они вообще не имеют ссылок/изменений). В этот момент решение, использующее прототипическое наследование, может внезапно стать очевидным. :)

+0

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

0

Мой коллега придумал одно из возможных решений. Как сказал @cloudfeet, это не прототип, но он работает.

В основном он установил привязку к другой функции, например, что, в свою очередь, называется функция _onRowClick, которая во время исполнения была бы отменена.

http://jsbin.com/uDEjuzeQ/16/edit

+0

Кажется, должен быть способ сделать это с помощью функции прокси-сервера jQuery, но я не смог заставить его работать. – Snekse

1

Вот код, который должен работать:

var BasicPage = function(){ 
    this.name="BasicPage"; 
    document.body.onclick=this._getClick(this); 
}; 
BasicPage.prototype._getClick=function(me){ 
    return function(e){ 
    console.log("target is:,",e.target); 
    console.log("this is:",me.name); 
    } 
}; 

var PageWithSections = function(){ 
    //initialise parent and it's instance members 
    BasicPage.call(this); 
    //override name 
    this.name="PageWithSections"; 
}; 
PageWithSections.prototype=Object.create(BasicPage.prototype); 
PageWithSections.prototype.constructor=PageWithSections; 

var sect = new PageWithSections(); 
document.body.click(); 

Следующий код демонстрирует, как можно продлить обработчик OnClick без копирования и вставки кода BasicPage у вас уже есть:

var BasicPage = function(){ 
    this.name="BasicPage"; 
    document.body.onclick=this._getClick(this); 
}; 
BasicPage.prototype._getClick=function(me){ 
    return function(e){ 
    console.log("re used code from BasicPage"); 
    console.log("target is:,",e.target); 
    console.log("this is:",me.name); 
    } 
}; 

var PageWithSections = function(){ 
    //initialise parent and it's instance members 
    BasicPage.call(this); 
    //override name 
    this.name="PageWithSections"; 
}; 
//set prototype chain 
PageWithSections.prototype=Object.create(BasicPage.prototype); 
PageWithSections.prototype.constructor=PageWithSections; 
//extend _getClick 
PageWithSections.prototype._getClick=function(me){ 
    var fn=BasicPage.prototype._getClick.call(me,me); 
    return function(e){ 
    //do BasicPage click code 
    fn(e); 
    //extended code 
    console.log("with a little extra from PageWithSections"); 
    }; 
}; 


var sect = new PageWithSections(); 
document.body.click(); 

Дополнительная информация о функциях прототипа и конструктора here. Введение должно быть очень полезно, и если у вас есть время, я бы предложил прочитать все, чтобы получить хорошее представление о прототипе JS.

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

  • Нет связанных вопросов^_^