среда, 29 февраля 2012 г.

Усовершенствование шаблона enrichment

Стоян Стефанов (Stoyan Stefanov) описывает в своей книге "JavaScript Шаблоны" ("JavaScript Patterns") в гл.6 шаблон "Заимствование конструктора" (к сожалению, в русском издании английские названия шаблонов были опущены и по-этому каноническое название этого шаблона мне пока не удалось найти, в том чиле и на сайте http://www.jspatterns.com/ этот шаблон не упомянут).

Этот шаблон очень напоминает то, что я в одном из предыдущих своих постов назвал "Enrichment", единственное отличие заключается в том, что он предлагает его использование в контексте наследования (в том числе предлагает на его основе реализацию множественного наследования), а не в контексте придания дополнительной функциональности уже сформированным объектам. Читатель, конечно, может считать это одним и тем же шаблоном, однако специфика применения в данном случае, на мой взгляд, имеет важное значение.

Немного попрактиковавшись, я пришёл к выводу о том, что шаблон enrichment луше будет всё-таки описывать именно простой функцией, не пытаясь делать вид, что это конструктор, начиная её не с заглавной буквы, а с приставки "to", что бы не путать её с настящим конструктором. Конструктора же из неё не выйдет просто потому, что, как справедливо указывает Стоян Стефанов в разделе недостатков этого шаблона, она не может прицепить к передаваемому ей объекту ссылку "__proto__" на прототип, а по-этому не может встроить его в модель наследования.

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

function EventW3C() {
    if (!('preventDefault' in this))
        this.preventDefault = function() {
            this.returnValue = false;
        };
    if (!('stopPropagation' in this))
        this.stopPropagation = function(){
            this.cancelBubble = true;
        };
    //Прочие реализации стандартных свойств и методов
    return this;
}
, теперь я пишу так, что, с моей точки зрения, более корректно:
function toW3CEvent(that) {
    for (var p in toW3CEvent)
        if (!(p in that) && toW3CEvent.hasOwnProperty(p) && p !== 'prototype')
            that[p] = toW3CEvent[p];
    return that;
}
toW3CEvent.preventDefault = function() { this.returnValue = false; };
toW3CEvent.stopPropagation = function() { this.cancelBubble = true; };
//Прочие реализации стандартных свойств и методов
Так, теперь для придания объекту event в IE6-8 функциональности стандартного W3C DOM объекта Event, можно вызвать эту функцию следующим образом:
handler.call(that, toW3CEvent(event));

Комментариев нет: