Ссылки на анонимные функции в Javascript - PullRequest
1 голос
/ 06 января 2011

В настоящее время я работаю над созданием ОЧЕНЬ простого класса Observer для проекта, над которым я работаю. Я успешно реализовал методы подписки, отписки и уведомления. Все работает точно так, как и ожидалось при использовании «обычных» функций (т. Е. Var f = function ()).

Однако, когда я передаю анонимную функцию методу подписки, а затем пытаюсь отписаться, передавая «ту же» анонимную функцию, она (как и ожидалось) не удаляет функцию из моего массива (в конце концов, они разные).

Вот мои методы подписки и отписки

this._subscribers = {};
subscribe: function(type, callback) {
    if ( isUndefined(this._subscribers[type]) ) {
        this._subscribers[type] = [];
    }
    this._subscribers[type].push(callback);
},
unsubscribe: function(type, callback) {
    if ( this._subscribers[type] instanceof Array ) {
        var index = this._subscribers[type].indexOf(callback);
        if ( index >= 0 ) {
            this._subscribers[type].splice(index, 1);
        }
    }
},

А вот код, с которым я тестирую:

var o = new gaf.events.Observable();
o.subscribe('testEvent', function(event) { alert('Got It!'); });
o.notify('testEvent');
// Correct alerts 'Got It!'
o.unsubscribe('testEvent', function(event) { alert('Got It!'); });
o.notify('testEvent')
// Incorrectly alerts 'Got It!'

Я знаю, что мог бы использовать объект (то есть: _subscribeers [event] = {}), а затем, когда что-то подписывалось, я мог добавить новое свойство, равное обратному вызову, и значение, равное обратному вызову. Это заставит JavaScript преобразовать обратный вызов в строку. Затем я мог бы найти его (при условии, что методы, переданные в sub / unsub точно такие же), используя эту строку.

Тем не менее, это мобильный проект, и я очень опасаюсь хранить строки, которые могут быть сотнями символов длиной до свойств, поскольку у нас может быть много подписчиков.

Есть ли другие способы сделать это? Существуют ли какие-нибудь МАЛЕНЬКИЕ (крошечные, даже) библиотеки хеширования, которые я могу использовать, чтобы, возможно, хэшировать строковое значение функции и использовать его в качестве свойства? Было бы лучше сохранить строковое значение обратного вызова (чтобы я мог сравнить с ним) в массиве (а не фактический обратный вызов) и использовать eval () для него?

Большое спасибо заранее !!

EDIT

Во-первых, спасибо всем за ответы!

По всем вопросам о функциях «Зачем даже передавать анонимные» -

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

Другая причина этого заключается в том, что происходит, если пользователь (сотрудник) этого класса Observable передает ему анонимную функцию и затем отписывается. Эта функция на самом деле не будет отписана и, следовательно, не будет очищена. У меня есть вещь против осиротевших данных:)

Может быть, другой вопрос, который мне следует задать, есть ли возможность проверить, является ли обратный вызов анонимным или нет? Я собираюсь предположить нет, но не больно спрашивать.

Ответы [ 4 ]

2 голосов
/ 06 января 2011

Нет ничего плохого в хранении всей строки;преждевременная оптимизация - это зло.

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

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

1 голос
/ 06 января 2011

клиенты, использующие Observer, должны хранить ссылку на функцию.

   var obsCallback = function() {

   }
   o.subscribe('test', obsCallback);
   ....
   o.unsubscribe('test', obsCallback);

другими словами, хранить ссылку на функцию около ...

0 голосов
/ 06 января 2011

Возможно, лучшим решением будет изменение кода с использованием вашей библиотеки

var f = function() { alert('Got It!'); };
o.subscribe('testEvent', f);
o.notify('testEvent');
o.unsubscribe('testEvent', f);
o.notify('testEvent');

Вы можете даже вернуть функцию из метода подписки

var f = o.subscribe('testEvent', function() { alert('Got It!'); });
// ...

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

0 голосов
/ 06 января 2011

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

В качестве альтернативы вы можете использовать необязательный аргумент 'id', но для этого потребуется излишне сложная бухгалтерия, чтобы избежать дублирования.

...