Javascript: присоединение событий из строки, оценка переменных в замыкании

Я уверен, что задал этот вопрос неправильно. Я пытаюсь передать строку, например onClick="someFunc(arg1,arg2...)", парсеру javascript.

Парсер должен создать событие onClick для someFunc с аргументами (arg1, arg2 и т. д.).

Моя проблема заключается в том, что по мере того, как текст проходит через синтаксический анализатор, область действия переменной, содержащей строковое имя someFunc, передается вниз, так что все прикрепленные события регистрируются как последняя объявленная строка.

В приведенном ниже коде attribute._onClick может быть строкой 'onClick="someFunc(arg1,arg2);" для одного элемента, за которым следует 'onClick="otherFunc(argA,argB);" для другого элемента, когда анализатор перемещается по строке.

Вывод в браузере (Firefox V14.01) имеет функцию события, всегда регистрируемую как otherFunc. Таким образом, f_name в замыкании не оценивается как переменная, а просто регистрируется как последнее значение f_name, объявленное при разборе всего блока.

Я не знаком с масштабом в той степени, в которой мне нужно быть, чтобы понять это. Кто-нибудь знает, как я могу прикрепить события таким образом (я пытаюсь не выходить за пределы синтаксического анализатора, чтобы добавить события)?

           temp = attributes._onClick ;
            var x = 0 ;
            var f_name,f_args ;
            while(temp[x] != '') {
                temp[x] = temp[x].replace(')','').split('(') ;//remove paranthesis and separate func name from args
                f_name = temp[x][0] ;
                f_args = temp[x][1].split(',') ;//turn string of args into array
                el.onclick = function() { window[f_name].apply(el,f_args) ; }
                x++ ;
            }

person Magic Lasso    schedule 31.07.2012    source источник
comment
Вы знаете, что значение onclick не обязательно должно быть вызовом функции, верно? Это могут быть любые операторы JavaScript.   -  person Pointy    schedule 31.07.2012


Ответы (1)


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

Переменная "f_name" общая для всех создаваемых вами функций. То есть, хотя каждая итерация цикла создает новую функцию, существует только одно «f_name». Таким образом, все функции видят в ней одно и то же значение, то есть значение, которое она имела на последней итерации.

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

               el.onclick = function(name) {
                return function() { window[name].apply(el,f_args) ; };
               }(f_name);

Интересно, что здесь, на SO, есть, вероятно, сотни вариантов этого вопроса.

person Pointy    schedule 31.07.2012
comment
Я попробовал код, который у вас есть здесь, и я предполагаю, что я не совсем понял, что вы делаете, но он не работает для меня. f_name по-прежнему использует только последнее присвоенное значение. Поправьте меня, если я ошибаюсь, но использование закрытия должно «установить» переменную и вернуть ее внешней функции? - person Magic Lasso; 31.07.2012
comment
Догадаться. Я еще не знаком с синтаксисом, но я использовал ваш ответ. Спасибо, Пойнти. - person Magic Lasso; 31.07.2012
comment
@MagicLasso хорошо, рад помочь - ключ в том, что в функции я использовал имя вместо f_name - я сделал это, чтобы было ясно, что я использую копию, но, возможно, это сбивало с толку. В любом случае, я рад, что это работает! - person Pointy; 31.07.2012