Задачка на понимание ООП
Всем доброго времени суток!
Читая и осваивая JavaScript, конкретно, ООП-раздел, наткнулся на короткую, но пока неподъёмную для меня задачку. "В системе имеется некоторое число объектов, которые сообщаются между собой с помощью событий. Написать на native JavaScript класс, который будет предоставлять им эту возможность. Реализовать на примере." Для себя я понял эту задачу так - нужно создать класс, который будет неким связующим звеном между объектами системы, с помощью которого они смогут отправлять и принимать данные друг от друга. Предварительные идеи - при создании нового объекта (объекты одного класса) на этапе конструктора записывать новый объект в массив объектов (изначально он будет пуст). Далее по логике каждый объект должен иметь методы наподобие SendMessage (здесь можно разбить на варианты SendToOne И SendToAll - то есть либо всем объектам массива либо конкретному) и ReceiveMessage - получение сообщения от объектов. Но есть вопросы по реализации - как реализовать получение и отсылку сообщений? То есть чтобы объект знал, от кого ему пришло сообщение, сохранял его у себя в каком-то свойстве и мы могли бы извлечь эти данные. Ну и не всё понятно с механизмом отправки. Буду благодарен за любые идеи и рекомендации. Готового кода не прошу, просто опишите, как вы видите решение такой задачи. Благодарю! :) |
Ivan_Ivanoff_24,
может быть паттерн "наблюдатель" (observer) имеется в виду? |
Цитата:
Цитата:
|
В javascript нет событий если не считать Dom, но никто не мешает их эмулировать. События это объект который хронит в себе ассоциативный массив (где ключ это имя события) массив обработчиков. Это совсем не сложно.
|
Ivan_Ivanoff_24,
И, кстати, объекты не могут общаться с помощью событий. Объекты обмениваются сообщениями, события тут не при чем. Другое дело, что событие само может являться объектом, и слать сообщения. Тот кто писал это задание сам, вероятно, слабо представляет, что такое ООП. |
/** * @class Base */ var Base = function Base() {}; Base.prototype = { /** * @private */ _events: null, /** * @method trigger * @param {String} eventName * @param {*|Array} [arg] * @returns @this */ trigger: function (eventName, arg) { var $Event = function (type) { this.type = type; }; if (!this._events || !this._events[eventName]) { return this; } if (!(arg instanceof Array)) { arg = [arg]; } var iteration = function () { var arrEvents = this._events[eventName].slice(); arrEvents.forEach(function (handler) { handler.apply(new $Event(eventName), arg); }); }.bind(this); iteration(); return this; }, /** * @method bind * @param {String|Object} eventName * @param {function|Array} [handler] * @returns @this */ bind: function (eventName, handler) { if (eventName == undefined) { console.log("Неверные параметры!"); return this; } if (typeof eventName == "object") { this.iterationObj(eventName, function (handler, eventName) { this.bind(eventName, handler); }.bind(this)); return this; } if (handler == undefined) { console.log("Неверные параметры!"); return this; } if (!this._events) { this._events = {}; } if (!this._events[eventName]) { this._events[eventName] = []; } if (!(handler instanceof Array)) { this._events[eventName].push(handler); } else { this._events[eventName] = this._events[eventName].concat(handler); } return this; }, /** * @method unbind * @param {String|Object} [eventName] * @param {function} [handler] * @returns @this */ unbind: function (eventName, handler) { if (eventName == undefined) { this._events = {}; return this; } else if (eventName instanceof Object) { for (var key in eventName) if (eventName.hasOwnProperty(key)) this.unbind(key, key[eventName]); return this; } if (handler == undefined) { if (this._events && eventName in this._events) { this._events[eventName] = []; return this; } return this; } for (var i = 0; i < this._events[eventName].length; i++) { if (this._events[eventName][i] == handler) { this._events[eventName].splice(i, 1); break; } } return this; } }; var Obj1 = new Base(); Obj1.bind("some event", function () { alert("some event!"); }); Obj1.bind("some event", function () { alert("some event!2"); }); Obj1.trigger("some event", []); Раньше я использовал этот объект как базовый класс. Я наследовался от него и все мои объекты могли общаться событиями. Сейчас я использую события взятые из backbone (хотя в целом там тоже самое) |
Цитата:
O={ sendTo: function(obj, msg){obj.receiveFrom(this, msg)}, receiveFrom: function(sender, msg){console.log(this.name+": I have receive the message '"+msg+"' from "+sender.name)}, create: function(name){var o=Object.create(this); window[name]=o; o.name=name} } O.create("object1") O.create("object2") object1.sendTo(object2, "Hello!") // object2: I have receive the message 'Hello!' from object1 |
Цитата:
|
Цитата:
|
tsigel,
Ну и какое же они имеют отношение к документу? Если какой то придурок когда то что-то как-то назвал, другие не обязаны повторять за ним эту глупость. |
Цитата:
Цитата:
Цитата:
ES6 пока только готовится к релизу, но им уже можно пользоваться почти на полную мощь с помощью трансляции. |
Цитата:
Цитата:
|
Цитата:
И, пожалуйста, расскажите хотя бы вкратце, что происходит в классе Base из Вашего примера, назначение его свойств и методов. Благодарю! |
Erolast, Благодарю за ЦУ, обязательно учту и воспользуюсь =)
|
Цитата:
В принципе, Вы можете добавить сахарку: O=function(name){this.name=name} O.prototype={ sendTo: function(obj, msg){obj.receiveFrom(this, msg)}, receiveFrom: function(sender, msg){console.log(this.name+": I have receive the message '"+msg+"' from "+sender.name)}, } object1=new O("object1") object2=new O("object2") object1.sendTo(object2, "Hello!") // object2: I have receive the message 'Hello!' from object1 Тогда формально не докопаешься. |
nbq, спасибо огромное! Заодно подробнее ознакомился с prototype и увидел, как можно красивее "завернуть" туда функционал.
|
Цитата:
|
Цитата:
|
Цитата:
Он имеет 3 метода: 1) bind - подписываемся на события. Он принимает либо собыитие и обработчик, либо объект, в котором ключ - это имя события, а значение - обработчик. Пример использования: new Base().bind("some event", function handler() {...}); new Base().bind({ "some event 1": function handler1() {...}, "some event 2": function handler2() {...} }); 2) unbind - отписываемся от событий. var baseExtended = ... //объект с подписанными обработчиками. baseExtended.unbind() // снимет все обработчики со всех событий объекта baseExtended.unbind("event") // снимет все обработчики с именем события "event"; baseExtended.unbind("event", handler) // снимит конкретный обработчик который равен передаваемой функции (как removeEventListener) 3) - trigger - метод который запускает события (1-й аргумент - имя события, второй массив аргуметов которые придут в функции - слушатели); baseExtended.trigger("event", [baseExtended]) // запускаем событие "event", всем слушателям придет первым аргументом автор события |
Часовой пояс GMT +3, время: 23:44. |