Еще раз про очистку массива в js(интересный случай)
Добрый день, уважаемые новички и ниндзи!
Почти каждый виджет в моем проекте, навешен его реализующий класс, во время рендеринга виджетов менеджер объектов содержащий массив экземпляров классов виджетов, этот массив чистит, и заполняет заново у меня это прописано вот так: this.widgets = []; // далее в цикле по селекторам создает через new для блоков виджетов функции их обрабатывающие В одном виджете я заметил, что при нажатии на кнопку, после которой происходит переинициализация массива widgets действие при следующем клике(n - ном клике) выполяется 2^(n-1) раз, пофиксил отвязкой handler'а перед вызовом функции реинициализации менеджера, но выходит, что объекты-функции из массива не удаляются, а это ест память, как это объяснить и исправить? :help: |
Сейчас протестил, и
this.widgets.length = 0 не помогает |
Цитата:
И зачем тебе вообще этот массив? |
Массив экземпляров объектов функции виджетов, которые содержат обработчики событий на элементах каждого виджета в себе(на странице может быть несеолько виджжетов одного типа)
|
Цитата:
Цитата:
|
даже проход с удалением и реинициализацией нулем не помог
|
Цитата:
|
Цитата:
|
Какая разница зачем и как сделано, сделано все исходя из требований к проге, проще говория есть массив объектов которые содержат методы для работы с виджетом, вопрос в другом, почему после чистки массива некоторые обработчики срабатывают 2, 4, 8, 16... раз
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
1. допустим есть виджет текстового поля(с множеством значений), естественно у каждого поля свой id в базе и оно уникально, они принадлежат объекту, каждое поле отображается на клиент в виде виджета(в каждом производятся операции например удаление, добавление значения, переименование поля, перерисовка).
2. тогда есть класс виджета тектового поля от которого элементу виджета сопоставляет функции для управления записью в нем, 3. Теперь допустим в объекте 3 поля, на каждое естественно, надо навесить отдельный экземпляр объектов класса WidgetTextField, для этого используется глобальный менеджер, который инициализирует такие объекты для ВСЕХ виджетов на странице. |
допусти в виджете объекта мы раз нажади кнопку добавить поле;
1. поле добавилось 2. происходит рендеринг виджета, в котором менеджер перезапускается кликнули 2 раз, (1,2) выполнилось 2 раза, 3 раз - 4 раза, а менеджер говорит на консоль каждый раз когда запускается |
Но так происходит только в этом виджете, виджет текстового поля при нажатии на кнопку добавляния значения всегда 1 раз срабатывает, и напомню, каждый клик на виджете перезапускает менеджер.
|
Цитата:
Цитата:
|
Никакой не через жопу, все в соответствии с ооп на javascript, если ты не знаком с этим то не надо тут кричать что все через жопу, а вопрос простой и повторю его еще раз: почему после очистки массива хендлеры остаются
|
Manager = function() { // Срабатывает каждый раз при изменении блока #main_frame // Это нужно для того чтобы переинициализировать виджеты this.widgets = []; this.run = function () { console.log("manager runned ..."); w_blocks = $('.widget'); for(i in this.widgets) { delete this.widgets[i]; this.widgets[i] = 0; } this.widgets = []; for (var i = 0; i < w_blocks.length; i++) { $(w_blocks[i]).attr('w_id', i); var options = ($(w_blocks[i]).attr('options')); options = (options == undefined || options =="") ? ",{}" : "," + options; var call_str = "new " + $(w_blocks[i]).attr('widget') + "('[w_id=" + i + "]'" + options + ")"; console.log(call_str); this.widgets[i] = eval(call_str); } }; }; |
Примерный вывод
manager runned ... new ObjectsList('[w_id=0]',{'filters': {'need_fields': False}}) |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
может я что то не понимаю но спрошу !
зачем делать вот так ?? delete this.widgets[i]; /// undefined this.widgets[i] = 0; /// теперь undefined меняешь на 0 this.widgets = []; // и тут полностью очищаешь массив ! покажи как ты вешаешь события и удаляешь !! |
Все правильно понимаешь, ерунду он делает.
Тем более что через delete элементы массива удалять нельзя. |
да обход с удалением и инииализацией нулем я для теста сделал, в учебных пособиях говорится что достаточно сделать
arr = [] или arr.lenth = 0 Вот код одного из виджетов: function ObjectWidget(block, options) { Widget.apply(this, [block, options]); var self = this; self.options.widget = self.block.attr('widget'); self.obj_name = self.block.find('.obj_name').find('span').text(); self.options.obj_id = self.block.attr('obj_id'); self.block.find(".obj_name").click(function(){self.changeName(this)}); self.block.find(".delete").click(function(){self.del()}); self.block.find(".close").click(function(){self.close()}); self.block.find(".add_field").click(function(){self.add()}); var mfHeight = parseInt($('#container').css('height')); var hHeight = parseInt(self.block.find('.obj_w_header').css('height')); self.block.find('.scroll-pane').css('height', mfHeight-hHeight-15+'px'); self.block.find('.scroll-pane').jScrollPane(); } ObjectWidget.prototype.del = function () { this.options.action = "delete"; var result_container = $("#main_frame"); this.render(result_container); }; |
По сути, если удалить объект из массива, должен удалиться и обработчик, или объект не удаляется из за того что ссылка повешена на элементе? Но ведь я заменяю сам элемент либо через replaceWith(ajax_result) либо через html(ajax_result) потом запускаю менеджер
|
ты вешаешь на елемент DOM вот удаляй его или обработчик с него !
я Jquery к счастью плохо знаю но мне кажется что много у тебя обработчиков ! почитай о всплытие ! self.block.find(".obj_name").click(function(){self .changeName(this)}); self.block.find(".delete").click(function(){self.d el()}); self.block.find(".close").click(function(){self.cl ose()}); self.block.find(".add_field").click(function(){sel f.add()}); |
Цитата:
Цитата:
var ajax_result = $.getJSON("./widgets.json"); $(".widgets").replaceWith(ajax_result); Цитата:
Цитата:
|
я не говорю что я ООП мастер и js ниндзя, даже тут javascript.ru корявые статьи про наследование. Проверил это на своем опыте.
|
вешаешь одно события и можно легко управлять хоть 100 виджетами !
|
базовый класс:
function Widget(block, options) { this.options = eval(options); this.block = $(block); var self = this; // this.options.widget = this.block.attr('widget'); this.render = function(result_container) { if (result_container == undefined) result_container = this.block; $.ajax({ url: "/widget/", type: "GET", data: {"options": JSON.stringify(this.options) }, success: function (result) { $(result_container).empty().html(result); // empty добавил только что и тестю manager.run(); } }); }; this.query = function(request_handler) { $.ajax({ url: "/widget/", type: "GET", data: {"options": JSON.stringify(this.options) }, success: function (result) { request_handler(result); } }); }; this.replaceRender = function() { $.ajax({ url: "/widget/", type: "GET", data: {"options": JSON.stringify(this.options) }, success: function (result) { self.block.replaceWith(result); manager.run() } }); }; } |
что у тебя виджет делает ? (для интереса )
|
Цитата:
|
ясно!!
Erolast я не так понял ))) сори за навязывания ошибочного мнения )) |
Ну мне все ясно, надо юхать empty() перед заменой, он снимает все хандлеры, спасибо!!!:)
|
Цитата:
|
Цитата:
Цитата:
function Person(name) { this.name = name; } Person.prototype.render = function() { alert(this.name) } let person = new Person("Вася"); person.render(); Цитата:
Только бэкбон в чистом виде использовать не надо, он реализует лишь самый базовый функционал. К нему нужны довески - гугли Chaplin/Marionette, Rivets.js. И посмотри react.js, может, больше по душе придется. Цитата:
Цитата:
|
Часовой пояс GMT +3, время: 08:00. |