Pull to refresh

Comments 12

Пардонте, но knockout то почему тяжелый стал? Чем он вас не устраивает в маленьких фронт-эндах, но когда нужны модели…?
Всё хорошо, но только зачем вы заменяете нативный bind на ваш собственный?

Да и вы можете ещё ужать код используя jQuery.Event или DOM Event constructors
function classA(container) {
  this.container = container;
}
classA.prototype.on = function(eType, handler) {
  this.container.addEventListener(eType, handler);
}
classA.prototype.un = function(eType, handler) {
  this.container.removeEventListener(eType, handler);
}
classA.prototype.fire = function(eType, data) {
  this.container.dispatchEvent(
    new CustomEvent(eType, {bubbles : true, cancelable : true, detail : data})
  );
}

var A = new classA(document.querySelector("#test"));
A.on("testns:someevent1", function(e){  console.log(e.detail + "")  })
A.fire("testns:someevent1", {toString : function(){return "test"}})

Код банальный, я знаю. Но тут основное нативный new CustomEvent()
Добавлю, что наследование на прототипах со ссылкой на super банально делается через Object.create
function inherit(Child, Parent) {
	(Child.prototype = Object.create(Child["superclass"] = Parent.prototype)).constructor = Child;
};

function classB() {
  classB.superclass.constructor.apply(this, arguments)
}
inherit(classB, classA);

Это конечно всё уже можно обернуть
Спасибо, очень круто
ну типа зачем еще один велосипед, у которого никомьюнити ни будущего, уж простите
Все с чего-то начинают.
Вот именно. Кстати, определенное будущее точно есть — фреймворк будет использоваться в достаточно серьезном проекте. Жаль, что пост в начале ушел в минус — хотелось получить побольше фидбека, и кого-нибудь, кто захотел бы присоединиться.
Насчет фреймворка вы загнули. Фреймворк подразумевает некоторые заготовки, иерархию классов и т.п. У вас же просто набор функций, упрощающий реализацию одной из задач.
Кстати, подход не новый и встречается во многих библиотеках. И у вас не реализован метод unsubscribe. Или у вас объекты никогда не разрушаются, не «отвязываются» друг от друга?
superCall/superMethod конечно неплохой синтаксический сахар, но это требует специальной недешевой обертки. Если у вас пара десятков/сотен объектов, с простой логикой, то тут проблем нет. Когда переходим к бОльшим порядкам, то эта обертка дает о себе знать. В нашем фреймворке мы отказались от этого, так как отказ от обертки дал ускорение в 2 раза. Да писать SuperClass.prototype.method.apply(this, arguments) несколько дольше чем this.superCall(), но мы сделали выбор в пользу скорости (отлаживать, кстати, тоже стало проще, да и переопределять методы класса после его создания, что важно для тестирования).

Странно, что вы считаете тяжелыми одни библиотеки, а jQuery таковой не считаете.Ваше решение зависит (внезапно) от jQuery, т.к. в двух местах используется $.extend.
Спасибо за фидбек, отвечу по порядку:

1. Все-таки это фреймворк. Он как раз содержит заготовку всех классов и предлагает определенную политику построения приложения. То, что иерархия состоит всего из одного элемента, не делает ее менее соответствующей понятию «иерархия».

2. Основная проблема SuperClass.prototype.method.apply(this, arguments) — это даже не длинный синтаксис — а тот факт, что не всегда известен точный предок, содержащий такую же функцию. Если цепочка наследования классов составляет хотя бы несколько звеньев, вы запаритесь в голове держать, какая функция в каком предке имплементирована.

Насчет отладки — да, отладка немного усложняется — т.к. в прототипе класса хранится не сам метод, а его обертка. Для фикса этой проблемы в саму обертку добавлено свойство _originalMethod, указывающее на оригинал.

Обертка действительно немного утяжеляет, но это не зависит от объема, как вы говорите — утяжеляются только прототипы, которые не множатся при создании новых объектов. Насчет скорости — согласен. Однако, ускорение в два раза возможно только. если сама функция выполняет всего пару действий. Если функции крупные, то обертка, которая делает пару присваиваний, будет незаметной. Мне сложно представить задачу, в которой используются простейшие функции, но при этом скорость играет существенную роль.

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

4. jQuery все-таки является must-have для большинства проектов, даже с простым фронтэндом. Поэтому кажется логичным его использовать. Но, думаю, вы тут правы и правильнее было бы включить код extend во фреймворк (или добавить возможность использовать extend из другой либы, вроде underscore);
2.
не всегда известен точный предок, содержащий такую же функцию. Если цепочка наследования классов составляет хотя бы несколько звеньев, вы запаритесь в голове держать, какая функция в каком предке имплементирована.

Это не нужно помнить, нужно только знать, что этот метод был определен в предках (а иначе зачем тогда вызывать superCall?). Вызывайте всегда метод класса от которого унаследовались, если в нем нет метода, но есть в предках он все равно будет доступен через цепочку прототипов. То есть следующий код должен работать без проблем:
var A = _n.Root.extend({
  method: function(){
    console.log('A.method');
  }
});
var B = A.extend({});
var C = B.extend({
  method: function(){
    B.prototype.method.call(this);
    console.log('C.method');
  }
});

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

Вы недооцениваете влияние обертки.
a) В два раза увеличивается число функций, размер стека вызова, областей видимости и т.д. По сути у вас на каждый метод добавляется собственное замыкание. Но это не самое страшное.
b) Любой вызов метода в вашем случае приводит к записи в объект. В вашей реализации это 4 записи (меняем и восстанавливаем _superMethod и _superCall) на одну оригинальную функцию метода. Присваивание, которым вы пренебрегаете, бывает разным. Если вы присваиваете переменной, то можно считать что это никак не влияет на скорость. Если вы присваиваете свойству объекта, то это поиск свойства у объекта (включая цепочку прототипов) и только потом присвоение — что имеет уже другую стоимость. К тому же делая присвоение вы выводите все ваши методы в разряд имеющих т.н. side effect, даже там где его в принципе нет, что лишает интерпретатор возможности производить оптимизации (от которых в современном мире сильно зависит скорость).
c) А еще вы создаете замыкание и объект в каждом вызове обертки.
Так что тут не идет речь о двух присваиваниях.
Опять же, повторюсь, для простых вещей с небольшим количеством инстансов проблем не будет: в сущности, между 10ms и 20ms разницы никакой. Но когда речь идет о 250ms и 500ms, то разница очень даже ощутима.

4. Никто вам не запрещает использовать jQuery — ваше право. Только нужно в таком случае указывать, что есть зависимость от него.
Название такое выбрали… как бы не пролетело сквозь рынок, никого и ничего не задев.
Sign up to leave a comment.

Articles